From 61dbe1bb6bde8c57b1dd2ba784fa4d881d1626a1 Mon Sep 17 00:00:00 2001 From: Hanabi <317387557+Hanabi9248@users.noreply.github.com> Date: Mon, 26 Oct 2026 13:14:00 +0800 Subject: [PATCH 1/2] fix: include index zero in reverse case-insensitive search Check index zero in the reverse-search loop so an otherwise matching prefix is not missed. Preserve the existing starting-index and empty-input handling and add standalone regressions against the complete StringUtil. Signed-off-by: Hanabi <317387557+Hanabi9248@users.noreply.github.com> --- .../highgo/cloud/util/toolkit/StringUtil.java | 2 +- tests/StringUtilReverseSearchRegression.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/StringUtilReverseSearchRegression.java diff --git a/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java b/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java index 9398671..77fd00c 100644 --- a/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java +++ b/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java @@ -834,7 +834,7 @@ public static int lastIndexOf(final CharSequence str, final CharSequence searchS return str.toString().lastIndexOf(searchStr.toString(), fromIndex); } - for (int i = fromIndex; i > 0; i--) { + for (int i = fromIndex; i >= 0; i--) { if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { return i; } diff --git a/tests/StringUtilReverseSearchRegression.java b/tests/StringUtilReverseSearchRegression.java new file mode 100644 index 0000000..edda37b --- /dev/null +++ b/tests/StringUtilReverseSearchRegression.java @@ -0,0 +1,40 @@ +import com.highgo.cloud.util.toolkit.StringUtil; + +/** JDK assertion runner; the complete production class uses real Spring Core. */ +public final class StringUtilReverseSearchRegression { + private static int failures; + + private static void check(String name, int expected, int actual) { + if (expected != actual) { + failures++; + System.err.println("FAIL " + name + ": expected " + expected + " but was " + actual); + } else { + System.out.println("PASS " + name); + } + } + + public static void main(String[] args) { + check("two-argument-prefix", 0, + StringUtil.lastIndexOfIgnoreCase("ABCxyz", "abc")); + check("three-argument-zero-start", 0, + StringUtil.lastIndexOfIgnoreCase("abcABC", "abc", 0)); + check("generic-identical-case-at-zero", 0, + StringUtil.lastIndexOf("abc", "abc", 0, true)); + check("charsequence-prefix", 0, + StringUtil.lastIndexOfIgnoreCase( + new StringBuilder("AbCd"), new StringBuilder("aB"), 4)); + + check("case-sensitive-zero-control", 0, + StringUtil.lastIndexOf("abc", "abc", 0, false)); + check("later-match-control", 3, + StringUtil.lastIndexOfIgnoreCase("aBcAbC", "abc")); + check("absent-control", -1, + StringUtil.lastIndexOfIgnoreCase("abc", "z")); + check("empty-needle-control", 0, + StringUtil.lastIndexOfIgnoreCase("abc", "", 0)); + if (failures != 0) { + throw new AssertionError(failures + " reverse-search cases failed"); + } + } +} + From c8da512f6deb620af3e69f868b8d01f68910d171 Mon Sep 17 00:00:00 2001 From: Hanabi <317387557+Hanabi9248@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:51:07 +0800 Subject: [PATCH 2/2] fix(toolkit): compare CharSequence text in case-sensitive equality Keep the existing reverse-search correction and null/case policies while comparing builder, buffer and String operands by textual contents. Signed-off-by: Hanabi <317387557+Hanabi9248@users.noreply.github.com> Assisted-by: OpenAI gpt-6.1-sol --- .../highgo/cloud/util/toolkit/StringUtil.java | 2 +- ...tringUtilCharSequenceEqualsRegression.java | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/StringUtilCharSequenceEqualsRegression.java diff --git a/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java b/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java index 77fd00c..0bcc35d 100644 --- a/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java +++ b/common/src/main/java/com/highgo/cloud/util/toolkit/StringUtil.java @@ -969,7 +969,7 @@ public static boolean equals(CharSequence str1, CharSequence str2, boolean ignor if (ignoreCase) { return str1.toString().equalsIgnoreCase(str2.toString()); } else { - return str1.equals(str2); + return str1.toString().equals(str2.toString()); } } diff --git a/tests/StringUtilCharSequenceEqualsRegression.java b/tests/StringUtilCharSequenceEqualsRegression.java new file mode 100644 index 0000000..6f9182d --- /dev/null +++ b/tests/StringUtilCharSequenceEqualsRegression.java @@ -0,0 +1,47 @@ +import com.highgo.cloud.util.toolkit.StringUtil; + +/** Exercises the complete production class and its real Spring superclass. */ +public final class StringUtilCharSequenceEqualsRegression { + private static int failures; + + private static void check(String name, boolean expected, boolean actual) { + if (expected != actual) { + failures++; + System.err.println("FAIL " + name + ": expected " + expected + " but was " + actual); + } else { + System.out.println("PASS " + name); + } + } + + public static void main(String[] args) { + check("distinct-builders-two-argument", true, + StringUtil.equals(new StringBuilder("same"), new StringBuilder("same"))); + check("distinct-buffers-explicit-false", true, + StringUtil.equals(new StringBuffer("same"), new StringBuffer("same"), false)); + check("string-to-builder", true, + StringUtil.equals("same", new StringBuilder("same"))); + check("builder-to-string", true, + StringUtil.equals(new StringBuilder("same"), "same")); + check("buffer-to-builder", true, + StringUtil.equals(new StringBuffer("same"), new StringBuilder("same"), false)); + check("builder-to-buffer", true, + StringUtil.equals(new StringBuilder("same"), new StringBuffer("same"), false)); + + check("string-value-control", true, + StringUtil.equals(new String("same"), new String("same"))); + check("unequal-content-control", false, + StringUtil.equals(new StringBuilder("left"), new StringBuffer("right"))); + check("case-sensitive-control", false, + StringUtil.equals(new StringBuilder("Same"), new StringBuffer("same"), false)); + check("ignore-case-control", true, + StringUtil.equalsIgnoreCase(new StringBuilder("Same"), new StringBuffer("same"))); + StringBuilder shared = new StringBuilder("same"); + check("same-instance-control", true, StringUtil.equals(shared, shared)); + check("both-null-control", true, StringUtil.equals(null, null)); + check("left-null-control", false, StringUtil.equals(null, new StringBuilder("same"))); + check("right-null-control", false, StringUtil.equals(new StringBuffer("same"), null, false)); + if (failures != 0) { + throw new AssertionError(failures + " CharSequence equality cases failed"); + } + } +}