diff --git a/ProgressOfTesting.txt b/ProgressOfTesting.txt index cd77b87..ff0f1b7 100644 --- a/ProgressOfTesting.txt +++ b/ProgressOfTesting.txt @@ -1,16 +1,16 @@ -[ ] 未开始测试 - 3 (4.84%) -[-] 测试未完成 - 5 (8.06%) -[Y] 测试完成 - 32 (51.61%) -[x] 无需测试 - 22 (35.48%) +[ ] 未开始测试 - 0 (0.00%) +[*] 测试未完成 - 5 (8.06%) +[Y] 测试完成 - 35 (56.45%) +[-] 无需测试 - 22 (35.48%) xyz.zhouxy.plusone.commons ├───annotation - │ ReaderMethod.java [x] - │ StaticFactoryMethod.java [x] - │ UnsupportedOperation.java [x] - │ ValueObject.java [x] - │ Virtual.java [x] - │ WriterMethod.java [x] + │ ReaderMethod.java [-] + │ StaticFactoryMethod.java [-] + │ UnsupportedOperation.java [-] + │ ValueObject.java [-] + │ Virtual.java [-] + │ WriterMethod.java [-] │ ├───base │ BoolRef.java [Y] @@ -27,46 +27,46 @@ xyz.zhouxy.plusone.commons │ CollectionTools.java [Y] │ ├───constant - │ PatternConsts.java [ ] - │ RegexConsts.java [ ] + │ PatternConsts.java [Y] + │ RegexConsts.java [Y] │ ├───exception - │ │ DataNotExistsException.java [x] + │ │ DataNotExistsException.java [-] │ │ ParsingFailureException.java [Y] │ │ ExceptionType.java [Y] │ │ │ ├───business - │ │ BizException.java [x] + │ │ BizException.java [-] │ │ InvalidInputException.java [Y] - │ │ RequestParamsException.java [x] + │ │ RequestParamsException.java [-] │ │ │ └───system - │ DataOperationResultException.java [x] - │ NoAvailableMacFoundException.java [x] - │ SysException.java [x] + │ DataOperationResultException.java [-] + │ NoAvailableMacFoundException.java [-] + │ SysException.java [-] │ ├───function - │ BoolUnaryOperator.java [x] - │ CharUnaryOperator.java [x] - │ Executable.java [x] - │ OptionalSupplier.java [x] + │ BoolUnaryOperator.java [-] + │ CharUnaryOperator.java [-] + │ Executable.java [-] + │ OptionalSupplier.java [-] │ PredicateTools.java [Y] - │ ThrowingConsumer.java [x] - │ ThrowingPredicate.java [x] - │ ThrowingSupplier.java [x] - │ ToOptionalBiFunction.java [x] - │ ToOptionalFunction.java [x] + │ ThrowingConsumer.java [-] + │ ThrowingPredicate.java [-] + │ ThrowingSupplier.java [-] + │ ToOptionalBiFunction.java [-] + │ ToOptionalFunction.java [-] │ ├───model │ │ Chinese2ndGenIDCardNumber.java [Y] - │ │ Gender.java [x] + │ │ Gender.java [-] │ │ IDCardNumber.java [Y] │ │ ValidatableStringRecord.java [Y] │ │ │ └───dto - │ PageResult.java [-] - │ PagingAndSortingQueryParams.java [-] - │ PagingParams.java [-] + │ PageResult.java [*] + │ PagingAndSortingQueryParams.java [*] + │ PagingParams.java [*] │ UnifiedResponse.java [Y] │ ├───time @@ -74,10 +74,10 @@ xyz.zhouxy.plusone.commons │ YearQuarter.java [Y] │ └───util - ArrayTools.java [-] + ArrayTools.java [*] 61 AssertTools.java [Y] BigDecimals.java [Y] - DateTimeTools.java [-] + DateTimeTools.java [*] 83 Enumeration.java [Y] EnumTools.java [Y] IdGenerator.java [Y] @@ -85,7 +85,7 @@ xyz.zhouxy.plusone.commons Numbers.java [Y] OptionalTools.java [Y] RandomTools.java [Y] - RegexTools.java [ ] + RegexTools.java [Y] SnowflakeIdGenerator.java [Y] StringTools.java [Y] TreeBuilder.java [Y] diff --git a/src/main/java/xyz/zhouxy/plusone/commons/constant/PatternConsts.java b/src/main/java/xyz/zhouxy/plusone/commons/constant/PatternConsts.java index ad5b555..4d8e03b 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/constant/PatternConsts.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/constant/PatternConsts.java @@ -27,33 +27,70 @@ import java.util.regex.Pattern; */ public final class PatternConsts { - /** yyyyMMdd */ + /** + * yyyyMMdd + * + * @see RegexConsts#BASIC_ISO_DATE + *

+ */ public static final Pattern BASIC_ISO_DATE = Pattern.compile(RegexConsts.BASIC_ISO_DATE); - /** yyyy-MM-dd */ + /** + * yyyy-MM-dd + * + * @see RegexConsts#ISO_LOCAL_DATE + */ public static final Pattern ISO_LOCAL_DATE = Pattern.compile(RegexConsts.ISO_LOCAL_DATE); - /** 密码 */ + /** + * 密码 + * + * @see RegexConsts#PASSWORD + */ public static final Pattern PASSWORD = Pattern.compile(RegexConsts.PASSWORD); - /** 验证码 */ + /** + * 验证码 + * + * @see RegexConsts#CAPTCHA + */ public static final Pattern CAPTCHA = Pattern.compile(RegexConsts.CAPTCHA); - /** 邮箱地址 */ + /** + * 邮箱地址 + * + * @see RegexConsts#EMAIL + */ public static final Pattern EMAIL = Pattern.compile(RegexConsts.EMAIL); - /** 中国大陆手机号 */ + /** + * 中国大陆手机号 + * + * @see RegexConsts#MOBILE_PHONE + */ public static final Pattern MOBILE_PHONE = Pattern.compile(RegexConsts.MOBILE_PHONE); - /** 用户名 */ + /** + * 用户名 + * + * @see RegexConsts#USERNAME + */ public static final Pattern USERNAME = Pattern.compile(RegexConsts.USERNAME); - /** 昵称 */ + /** + * 昵称 + * + * @see RegexConsts#NICKNAME + */ public static final Pattern NICKNAME = Pattern.compile(RegexConsts.NICKNAME); - /** 中国第二代居民身份证 */ + /** + * 中国第二代居民身份证 + * + * @see RegexConsts#CHINESE_2ND_ID_CARD_NUMBER + */ public static final Pattern CHINESE_2ND_ID_CARD_NUMBER - = Pattern.compile(RegexConsts.CHINESE_2ND_ID_CARD_NUMBER); + = Pattern.compile(RegexConsts.CHINESE_2ND_ID_CARD_NUMBER, Pattern.CASE_INSENSITIVE); private PatternConsts() { throw new IllegalStateException("Utility class"); diff --git a/src/main/java/xyz/zhouxy/plusone/commons/constant/RegexConsts.java b/src/main/java/xyz/zhouxy/plusone/commons/constant/RegexConsts.java index f1bad7f..9730ce1 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/constant/RegexConsts.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/constant/RegexConsts.java @@ -24,9 +24,9 @@ package xyz.zhouxy.plusone.commons.constant; */ public final class RegexConsts { - public static final String BASIC_ISO_DATE = "^(?\\d{4})(?\\d{2})(?\\d{2})"; + public static final String BASIC_ISO_DATE = "^(?\\d{4,9})(?\\d{2})(?
\\d{2})"; - public static final String ISO_LOCAL_DATE = "^(?\\d{4})-(?\\d{2})-(?\\d{2})"; + public static final String ISO_LOCAL_DATE = "^(?\\d{4,9})-(?\\d{2})-(?
\\d{2})"; public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[\\w\\\\!#$%&'*\\+\\-/=?^`{|}~@\\(\\)\\[\\]\",\\.;':><]{8,32}$"; @@ -38,12 +38,12 @@ public final class RegexConsts { public static final String MOBILE_PHONE = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$"; - public static final String USERNAME = "^[\\w_.@\\\\]{4,36}$"; + public static final String USERNAME = "^[\\w-_.@]{4,36}$"; - public static final String NICKNAME = "^[\\w_.@\\\\]{4,36}$"; + public static final String NICKNAME = "^[\\w-_.@]{4,36}$"; public static final String CHINESE_2ND_ID_CARD_NUMBER - = "^(?(?(?\\d{2})\\d{2})\\d{2})(?\\d{8})\\d{2}(?\\d)([\\dXx])$"; + = "^(?(?(?\\d{2})\\d{2})\\d{2})(?\\d{8})\\d{2}(?\\d)([\\dX])$"; private RegexConsts() { throw new IllegalStateException("Utility class"); diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/RegexTools.java b/src/main/java/xyz/zhouxy/plusone/commons/util/RegexTools.java index 34dfb5c..53551f8 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/util/RegexTools.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/util/RegexTools.java @@ -89,22 +89,6 @@ public final class RegexTools { return getPatternsInternal(patterns); } - /** - * 手动缓存 Pattern 实例。 - * - * @param pattern 要缓存的 {@link Pattern} 实例 - * @return 缓存的 Pattern 实例。如果缓存已满,则返回 {@code null}。 - */ - public static Pattern cachePattern(final Pattern pattern) { - AssertTools.checkNotNull(pattern, "The pattern can not be null."); - if (PATTERN_CACHE.size() >= MAX_CACHE_SIZE) { - return null; - } - final String patternStr = pattern.pattern(); - final Pattern pre = PATTERN_CACHE.putIfAbsent(patternStr, pattern); - return pre != null ? pre : pattern; - } - /** * 判断 {@code input} 是否匹配 {@code pattern}。 * @@ -285,7 +269,6 @@ public final class RegexTools { * 获取 {@link Pattern} 实例。 * * @param pattern 正则表达式 - * @param cachePattern 是否缓存 {@link Pattern} 实例 * @return {@link Pattern} 实例 */ @Nonnull diff --git a/src/test/java/xyz/zhouxy/plusone/commons/constant/PatternConstsTests.java b/src/test/java/xyz/zhouxy/plusone/commons/constant/PatternConstsTests.java new file mode 100644 index 0000000..88304d6 --- /dev/null +++ b/src/test/java/xyz/zhouxy/plusone/commons/constant/PatternConstsTests.java @@ -0,0 +1,235 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package xyz.zhouxy.plusone.commons.constant; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.regex.Matcher; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public // +class PatternConstsTests { + + // ================================ + // #region - BASIC_ISO_DATE + // ================================ + + @Test + void testBasicIsoDate_ValidDate() { + Matcher matcher = PatternConsts.BASIC_ISO_DATE.matcher("20241229"); + assertTrue(matcher.matches()); + + assertEquals("2024", matcher.group(1)); + assertEquals("12", matcher.group(2)); + assertEquals("29", matcher.group(3)); + assertEquals("2024", matcher.group("yyyy")); + assertEquals("12", matcher.group("MM")); + assertEquals("29", matcher.group("dd")); + + // LeapYearFeb29() + assertTrue(PatternConsts.BASIC_ISO_DATE.matcher("20200229").matches()); + + // BoundaryMin() + assertTrue(PatternConsts.BASIC_ISO_DATE.matcher("00000101").matches()); + + // BoundaryMax() + assertTrue(PatternConsts.BASIC_ISO_DATE.matcher("9999999991231").matches()); + } + + @ParameterizedTest + @ValueSource(strings = { + "20231301", // InvalidMonth + "20230230", // InvalidDay + "20210229", // NonLeapYearFeb29 + }) + void testBasicIsoDate_InvalidDate_butMatches(String date) { + // 虽然日期有误,但这个正则无法判断。实际工作中,应使用日期时间 API。 + Matcher matcher = PatternConsts.BASIC_ISO_DATE.matcher(date); + assertTrue(matcher.matches()); + } + + @ParameterizedTest + @ValueSource(strings = { + "2023041", // TooShort + "99999999990415", // TooLong + "2023-04-15", // NonNumeric + }) + void testBasicIsoDate_InvalidDate_Mismatches(String date) { + Matcher matcher = PatternConsts.BASIC_ISO_DATE.matcher(date); + assertFalse(matcher.matches()); + } + + // ================================ + // #endregion - BASIC_ISO_DATE + // ================================ + + // ================================ + // #region - ISO_LOCAL_DATE + // ================================ + + @Test + void testIsoLocalDate_ValidDate() { + Matcher matcher = PatternConsts.ISO_LOCAL_DATE.matcher("2024-12-29"); + assertTrue(matcher.matches()); + assertEquals("2024", matcher.group("yyyy")); + assertEquals("12", matcher.group("MM")); + assertEquals("29", matcher.group("dd")); + + // LeapYearFeb29() + assertTrue(PatternConsts.ISO_LOCAL_DATE.matcher("2020-02-29").matches()); + + // BoundaryMin() + assertTrue(PatternConsts.ISO_LOCAL_DATE.matcher("0000-01-01").matches()); + + // BoundaryMax() + assertTrue(PatternConsts.ISO_LOCAL_DATE.matcher("999999999-12-31").matches()); + } + + @ParameterizedTest + @ValueSource(strings = { + "2023-13-01", // InvalidMonth + "2023-02-30", // InvalidDay + "2021-02-29", // NonLeapYearFeb29 + }) + void testIsoLocalDate_InvalidDate_butMatches(String date) { + // 虽然日期有误,但这个正则无法判断。实际工作中,应使用日期时间 API。 + Matcher matcher = PatternConsts.ISO_LOCAL_DATE.matcher(date); + assertTrue(matcher.matches()); + } + + @ParameterizedTest + @ValueSource(strings = { + "2023-04-1", // TooShort + "9999999999-04-15", // TooLong + "20230415", + }) + void testIsoLocalDate_InvalidDate_Mismatches(String date) { + Matcher matcher = PatternConsts.ISO_LOCAL_DATE.matcher(date); + assertFalse(matcher.matches()); + } + + // ================================ + // #endregion - ISO_LOCAL_DATE + // ================================ + + // ================================ + // #region - PASSWORD + // ================================ + + @Test + void testPassword_ValidPassword_Matches() { + assertTrue(PatternConsts.PASSWORD.matcher("Abc123!@#").matches()); + } + + @Test + void testPassword_InvalidPassword_Mismatches() { + assertFalse(PatternConsts.PASSWORD.matcher("Abc123 !@#").matches()); // 带空格 + assertFalse(PatternConsts.PASSWORD.matcher("Abc123!@# ").matches()); // 带空格 + assertFalse(PatternConsts.PASSWORD.matcher(" Abc123!@#").matches()); // 带空格 + assertFalse(PatternConsts.PASSWORD.matcher(" Abc123!@# ").matches()); // 带空格 + assertFalse(PatternConsts.PASSWORD.matcher("77553366998844113322").matches()); // 纯数字 + assertFalse(PatternConsts.PASSWORD.matcher("poiujhgbfdsazxcfvghj").matches()); // 纯小写字母 + assertFalse(PatternConsts.PASSWORD.matcher("POIUJHGBFDSAZXCFVGHJ").matches()); // 纯大写字母 + assertFalse(PatternConsts.PASSWORD.matcher("!#$%&'*\\+-/=?^`{|}~@()[]\",.;':").matches()); // 纯特殊字符 + assertFalse(PatternConsts.PASSWORD.matcher("sdfrghbv525842582752").matches()); // 没有小写字母 + assertFalse(PatternConsts.PASSWORD.matcher("SDFRGHBV525842582752").matches()); // 没有小写字母 + assertFalse(PatternConsts.PASSWORD.matcher("sdfrghbvSDFRGHBV").matches()); // 没有数字 + assertFalse(PatternConsts.PASSWORD.matcher("Abc1!").matches()); // 太短 + assertFalse(PatternConsts.PASSWORD.matcher("Abc1!Abc1!Abc1!Abc1!Abc1!Abc1!Abc1!").matches()); // 太长 + assertFalse(PatternConsts.PASSWORD.matcher("").matches()); + assertFalse(PatternConsts.PASSWORD.matcher(" ").matches()); + } + + // ================================ + // #endregion - PASSWORD + // ================================ + + // ================================ + // #region - EMAIL + // ================================ + + @Test + public void testValidEmails() { + assertTrue(PatternConsts.EMAIL.matcher("test@example.com").matches()); + assertTrue(PatternConsts.EMAIL.matcher("user.name+tag+sorting@example.com").matches()); + assertTrue(PatternConsts.EMAIL.matcher("user@sub.example.com").matches()); + assertTrue(PatternConsts.EMAIL.matcher("user@123.123.123.123").matches()); + } + + @Test + public void testInvalidEmails() { + assertFalse(PatternConsts.EMAIL.matcher(".username@example.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("@missingusername.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("plainaddress").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username..username@example.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username.@example.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@-example.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@-example.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@.com.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@.com.my").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@.com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@com.").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@example..com").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@example.com-").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@example.com.").matches()); + assertFalse(PatternConsts.EMAIL.matcher("username@example").matches()); + } + + // ================================ + // #endregion - EMAIL + // ================================ + + // ================================ + // #region - Chinese2ndIdCardNumber + // ================================ + + @ParameterizedTest + @ValueSource(strings = { + "44520019900101456X", + "44520019900101456x", + "445200199001014566", + }) + void testChinese2ndIdCardNumber_ValidChinese2ndIdCardNumber(String value) { + Matcher matcher = PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher(value); + assertTrue(matcher.matches()); + assertEquals("44", matcher.group("province")); + assertEquals("4452", matcher.group("city")); + assertEquals("445200", matcher.group("county")); + } + + @ParameterizedTest + @ValueSource(strings = { + "4452200199001014566", + "44520199001014566", + " ", + "", + }) + void testChinese2ndIdCardNumber_InvalidChinese2ndIdCardNumber(String value) { + assertFalse(PatternConsts.CHINESE_2ND_ID_CARD_NUMBER.matcher(value).matches()); + } + + // ================================ + // #endregion - Chinese2ndIdCardNumber + // ================================ +} diff --git a/src/test/java/xyz/zhouxy/plusone/commons/util/RegexToolsTests.java b/src/test/java/xyz/zhouxy/plusone/commons/util/RegexToolsTests.java new file mode 100644 index 0000000..3968a24 --- /dev/null +++ b/src/test/java/xyz/zhouxy/plusone/commons/util/RegexToolsTests.java @@ -0,0 +1,165 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package xyz.zhouxy.plusone.commons.util; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.jupiter.api.Test; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public +class RegexToolsTests { + + @Test + void getPattern_CachePatternTrue_ReturnsCachedPattern() { + String pattern = "abc"; + Pattern cachedPattern = RegexTools.getPattern(pattern, true); + Pattern patternFromCache = RegexTools.getPattern(pattern, true); + assertSame(cachedPattern, patternFromCache, "Pattern should be cached"); + } + + @Test + void getPattern_CachePatternFalse_ReturnsNewPattern() { + String pattern = "abc"; + Pattern pattern1 = RegexTools.getPattern(pattern, false); + Pattern pattern2 = RegexTools.getPattern(pattern, false); + assertNotSame(pattern1, pattern2, "Pattern should not be cached"); + } + + @Test + void getPattern_NullPattern_ThrowsException() { + assertThrows(NullPointerException.class, () -> { + RegexTools.getPattern(null, true); + }); + } + + @Test + void getPatterns_CachePatternTrue_ReturnsCachedPatterns() { + String[] patterns = {"abc", "def"}; + Pattern[] cachedPatterns = RegexTools.getPatterns(patterns, true); + Pattern[] patternsFromCache = RegexTools.getPatterns(patterns, true); + assertSame(cachedPatterns[0], patternsFromCache[0]); + assertSame(cachedPatterns[1], patternsFromCache[1]); + } + + @Test + void getPatterns_CachePatternFalse_ReturnsNewPatterns() { + String[] patterns = {"abc", "def"}; + Pattern[] patterns1 = RegexTools.getPatterns(patterns, false); + Pattern[] patterns2 = RegexTools.getPatterns(patterns, false); + assertNotSame(patterns1[0], patterns2[0]); + assertNotSame(patterns1[1], patterns2[1]); + } + + @Test + void getPatterns_NullPatterns_ThrowsException() { + assertThrows(NullPointerException.class, () -> { + RegexTools.getPatterns(null, true); + }); + } + + @Test + void matches_InputMatchesPattern_ReturnsTrue() { + String pattern = "abc"; + Pattern compiledPattern = Pattern.compile(pattern); + assertTrue(RegexTools.matches("abc", compiledPattern), "Input should match pattern"); + } + + @Test + void matches_InputDoesNotMatchPattern_ReturnsFalse() { + String pattern = "abc"; + Pattern compiledPattern = Pattern.compile(pattern); + assertFalse(RegexTools.matches("abcd", compiledPattern), "Input should not match pattern"); + } + + @Test + void matches_NullInput_ReturnsFalse() { + String pattern = "abc"; + Pattern compiledPattern = Pattern.compile(pattern); + assertFalse(RegexTools.matches(null, compiledPattern), "Null input should return false"); + } + + @Test + void matchesOne_InputMatchesOnePattern_ReturnsTrue() { + String[] patterns = {"abc", "def"}; + Pattern[] compiledPatterns = new Pattern[patterns.length]; + for (int i = 0; i < patterns.length; i++) { + compiledPatterns[i] = Pattern.compile(patterns[i]); + } + assertTrue(RegexTools.matchesOne("abc", compiledPatterns), "Input should match one pattern"); + } + + @Test + void matchesOne_InputDoesNotMatchAnyPattern_ReturnsFalse() { + String[] patterns = {"abc", "def"}; + Pattern[] compiledPatterns = new Pattern[patterns.length]; + for (int i = 0; i < patterns.length; i++) { + compiledPatterns[i] = Pattern.compile(patterns[i]); + } + assertFalse(RegexTools.matchesOne("xyz", compiledPatterns), "Input should not match any pattern"); + } + + @Test + void matchesAll_InputMatchesAllPatterns_ReturnsTrue() { + String[] patterns = {"abc", "abc"}; + Pattern[] compiledPatterns = new Pattern[patterns.length]; + for (int i = 0; i < patterns.length; i++) { + compiledPatterns[i] = Pattern.compile(patterns[i]); + } + assertTrue(RegexTools.matchesAll("abc", compiledPatterns), "Input should match all patterns"); + } + + @Test + void matchesAll_InputDoesNotMatchAllPatterns_ReturnsFalse() { + String[] patterns = {"abc", "def"}; + Pattern[] compiledPatterns = new Pattern[patterns.length]; + for (int i = 0; i < patterns.length; i++) { + compiledPatterns[i] = Pattern.compile(patterns[i]); + } + assertFalse(RegexTools.matchesAll("abc", compiledPatterns), "Input should not match all patterns"); + } + + @Test + void getMatcher_ValidInputAndPattern_ReturnsMatcher() { + String pattern = "abc"; + Pattern compiledPattern = Pattern.compile(pattern); + Matcher matcher = RegexTools.getMatcher("abc", compiledPattern); + assertNotNull(matcher, "Matcher should not be null"); + } + + @Test + void getMatcher_NullInput_ThrowsException() { + String pattern = "abc"; + Pattern compiledPattern = Pattern.compile(pattern); + assertThrows(NullPointerException.class, () -> { + RegexTools.getMatcher(null, compiledPattern); + }); + } + + @Test + void getMatcher_NullPattern_ThrowsException() { + final Pattern pattern = null; + assertThrows(NullPointerException.class, () -> { + RegexTools.getMatcher("abc", pattern); + }); + } +}