1 /* 2 * Copyright (C) 2010 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.base; 18 19 import static com.google.common.base.ReflectionFreeAssertThrows.assertThrows; 20 import static com.google.common.truth.Truth.assertThat; 21 22 import com.google.common.annotations.GwtCompatible; 23 import com.google.common.annotations.GwtIncompatible; 24 import com.google.common.annotations.J2ktIncompatible; 25 import com.google.common.testing.NullPointerTester; 26 import junit.framework.TestCase; 27 28 /** 29 * Unit test for {@link Strings}. 30 * 31 * @author Kevin Bourrillion 32 */ 33 @ElementTypesAreNonnullByDefault 34 @GwtCompatible(emulated = true) 35 public class StringsTest extends TestCase { testNullToEmpty()36 public void testNullToEmpty() { 37 assertEquals("", Strings.nullToEmpty(null)); 38 assertEquals("", Strings.nullToEmpty("")); 39 assertEquals("a", Strings.nullToEmpty("a")); 40 } 41 testEmptyToNull()42 public void testEmptyToNull() { 43 assertNull(Strings.emptyToNull(null)); 44 assertNull(Strings.emptyToNull("")); 45 assertEquals("a", Strings.emptyToNull("a")); 46 } 47 testIsNullOrEmpty()48 public void testIsNullOrEmpty() { 49 assertTrue(Strings.isNullOrEmpty(null)); 50 assertTrue(Strings.isNullOrEmpty("")); 51 assertFalse(Strings.isNullOrEmpty("a")); 52 } 53 testPadStart_noPadding()54 public void testPadStart_noPadding() { 55 assertSame("", Strings.padStart("", 0, '-')); 56 assertSame("x", Strings.padStart("x", 0, '-')); 57 assertSame("x", Strings.padStart("x", 1, '-')); 58 assertSame("xx", Strings.padStart("xx", 0, '-')); 59 assertSame("xx", Strings.padStart("xx", 2, '-')); 60 } 61 testPadStart_somePadding()62 public void testPadStart_somePadding() { 63 assertEquals("-", Strings.padStart("", 1, '-')); 64 assertEquals("--", Strings.padStart("", 2, '-')); 65 assertEquals("-x", Strings.padStart("x", 2, '-')); 66 assertEquals("--x", Strings.padStart("x", 3, '-')); 67 assertEquals("-xx", Strings.padStart("xx", 3, '-')); 68 } 69 testPadStart_negativeMinLength()70 public void testPadStart_negativeMinLength() { 71 assertSame("x", Strings.padStart("x", -1, '-')); 72 } 73 74 // TODO: could remove if we got NPT working in GWT somehow testPadStart_null()75 public void testPadStart_null() { 76 assertThrows(NullPointerException.class, () -> Strings.padStart(null, 5, '0')); 77 } 78 testPadEnd_noPadding()79 public void testPadEnd_noPadding() { 80 assertSame("", Strings.padEnd("", 0, '-')); 81 assertSame("x", Strings.padEnd("x", 0, '-')); 82 assertSame("x", Strings.padEnd("x", 1, '-')); 83 assertSame("xx", Strings.padEnd("xx", 0, '-')); 84 assertSame("xx", Strings.padEnd("xx", 2, '-')); 85 } 86 testPadEnd_somePadding()87 public void testPadEnd_somePadding() { 88 assertEquals("-", Strings.padEnd("", 1, '-')); 89 assertEquals("--", Strings.padEnd("", 2, '-')); 90 assertEquals("x-", Strings.padEnd("x", 2, '-')); 91 assertEquals("x--", Strings.padEnd("x", 3, '-')); 92 assertEquals("xx-", Strings.padEnd("xx", 3, '-')); 93 } 94 testPadEnd_negativeMinLength()95 public void testPadEnd_negativeMinLength() { 96 assertSame("x", Strings.padEnd("x", -1, '-')); 97 } 98 testPadEnd_null()99 public void testPadEnd_null() { 100 assertThrows(NullPointerException.class, () -> Strings.padEnd(null, 5, '0')); 101 } 102 103 @SuppressWarnings("InlineMeInliner") // test of method that doesn't just delegate testRepeat()104 public void testRepeat() { 105 String input = "20"; 106 assertEquals("", Strings.repeat(input, 0)); 107 assertEquals("20", Strings.repeat(input, 1)); 108 assertEquals("2020", Strings.repeat(input, 2)); 109 assertEquals("202020", Strings.repeat(input, 3)); 110 111 assertEquals("", Strings.repeat("", 4)); 112 113 for (int i = 0; i < 100; ++i) { 114 assertEquals(2 * i, Strings.repeat(input, i).length()); 115 } 116 117 assertThrows(IllegalArgumentException.class, () -> Strings.repeat("x", -1)); 118 assertThrows( 119 ArrayIndexOutOfBoundsException.class, () -> Strings.repeat("12345678", (1 << 30) + 3)); 120 } 121 122 @SuppressWarnings("InlineMeInliner") // test of method that doesn't just delegate testRepeat_null()123 public void testRepeat_null() { 124 assertThrows(NullPointerException.class, () -> Strings.repeat(null, 5)); 125 } 126 127 @SuppressWarnings("UnnecessaryStringBuilder") // We want to test a non-String CharSequence testCommonPrefix()128 public void testCommonPrefix() { 129 assertEquals("", Strings.commonPrefix("", "")); 130 assertEquals("", Strings.commonPrefix("abc", "")); 131 assertEquals("", Strings.commonPrefix("", "abc")); 132 assertEquals("", Strings.commonPrefix("abcde", "xyz")); 133 assertEquals("", Strings.commonPrefix("xyz", "abcde")); 134 assertEquals("", Strings.commonPrefix("xyz", "abcxyz")); 135 assertEquals("a", Strings.commonPrefix("abc", "aaaaa")); 136 assertEquals("aa", Strings.commonPrefix("aa", "aaaaa")); 137 assertEquals("abc", Strings.commonPrefix(new StringBuilder("abcdef"), "abcxyz")); 138 139 // Identical valid surrogate pairs. 140 assertEquals( 141 "abc\uD8AB\uDCAB", Strings.commonPrefix("abc\uD8AB\uDCABdef", "abc\uD8AB\uDCABxyz")); 142 // Differing valid surrogate pairs. 143 assertEquals("abc", Strings.commonPrefix("abc\uD8AB\uDCABdef", "abc\uD8AB\uDCACxyz")); 144 // One invalid pair. 145 assertEquals("abc", Strings.commonPrefix("abc\uD8AB\uDCABdef", "abc\uD8AB\uD8ABxyz")); 146 // Two identical invalid pairs. 147 assertEquals( 148 "abc\uD8AB\uD8AC", Strings.commonPrefix("abc\uD8AB\uD8ACdef", "abc\uD8AB\uD8ACxyz")); 149 // Two differing invalid pairs. 150 assertEquals("abc\uD8AB", Strings.commonPrefix("abc\uD8AB\uD8ABdef", "abc\uD8AB\uD8ACxyz")); 151 // One orphan high surrogate. 152 assertEquals("", Strings.commonPrefix("\uD8AB\uDCAB", "\uD8AB")); 153 // Two orphan high surrogates. 154 assertEquals("\uD8AB", Strings.commonPrefix("\uD8AB", "\uD8AB")); 155 } 156 157 @SuppressWarnings("UnnecessaryStringBuilder") // We want to test a non-String CharSequence testCommonSuffix()158 public void testCommonSuffix() { 159 assertEquals("", Strings.commonSuffix("", "")); 160 assertEquals("", Strings.commonSuffix("abc", "")); 161 assertEquals("", Strings.commonSuffix("", "abc")); 162 assertEquals("", Strings.commonSuffix("abcde", "xyz")); 163 assertEquals("", Strings.commonSuffix("xyz", "abcde")); 164 assertEquals("", Strings.commonSuffix("xyz", "xyzabc")); 165 assertEquals("c", Strings.commonSuffix("abc", "ccccc")); 166 assertEquals("aa", Strings.commonSuffix("aa", "aaaaa")); 167 assertEquals("abc", Strings.commonSuffix(new StringBuilder("xyzabc"), "xxxabc")); 168 169 // Identical valid surrogate pairs. 170 assertEquals( 171 "\uD8AB\uDCABdef", Strings.commonSuffix("abc\uD8AB\uDCABdef", "xyz\uD8AB\uDCABdef")); 172 // Differing valid surrogate pairs. 173 assertEquals("def", Strings.commonSuffix("abc\uD8AB\uDCABdef", "abc\uD8AC\uDCABdef")); 174 // One invalid pair. 175 assertEquals("def", Strings.commonSuffix("abc\uD8AB\uDCABdef", "xyz\uDCAB\uDCABdef")); 176 // Two identical invalid pairs. 177 assertEquals( 178 "\uD8AB\uD8ABdef", Strings.commonSuffix("abc\uD8AB\uD8ABdef", "xyz\uD8AB\uD8ABdef")); 179 // Two differing invalid pairs. 180 assertEquals("\uDCABdef", Strings.commonSuffix("abc\uDCAB\uDCABdef", "abc\uDCAC\uDCABdef")); 181 // One orphan low surrogate. 182 assertEquals("", Strings.commonSuffix("x\uD8AB\uDCAB", "\uDCAB")); 183 // Two orphan low surrogates. 184 assertEquals("\uDCAB", Strings.commonSuffix("\uDCAB", "\uDCAB")); 185 } 186 testValidSurrogatePairAt()187 public void testValidSurrogatePairAt() { 188 assertTrue(Strings.validSurrogatePairAt("\uD8AB\uDCAB", 0)); 189 assertTrue(Strings.validSurrogatePairAt("abc\uD8AB\uDCAB", 3)); 190 assertTrue(Strings.validSurrogatePairAt("abc\uD8AB\uDCABxyz", 3)); 191 assertFalse(Strings.validSurrogatePairAt("\uD8AB\uD8AB", 0)); 192 assertFalse(Strings.validSurrogatePairAt("\uDCAB\uDCAB", 0)); 193 assertFalse(Strings.validSurrogatePairAt("\uD8AB\uDCAB", -1)); 194 assertFalse(Strings.validSurrogatePairAt("\uD8AB\uDCAB", 1)); 195 assertFalse(Strings.validSurrogatePairAt("\uD8AB\uDCAB", -2)); 196 assertFalse(Strings.validSurrogatePairAt("\uD8AB\uDCAB", 2)); 197 assertFalse(Strings.validSurrogatePairAt("x\uDCAB", 0)); 198 assertFalse(Strings.validSurrogatePairAt("\uD8ABx", 0)); 199 } 200 201 @SuppressWarnings("LenientFormatStringValidation") // Intentional for testing. testLenientFormat()202 public void testLenientFormat() { 203 assertEquals("%s", Strings.lenientFormat("%s")); 204 assertEquals("5", Strings.lenientFormat("%s", 5)); 205 assertEquals("foo [5]", Strings.lenientFormat("foo", 5)); 206 assertEquals("foo [5, 6, 7]", Strings.lenientFormat("foo", 5, 6, 7)); 207 assertEquals("%s 1 2", Strings.lenientFormat("%s %s %s", "%s", 1, 2)); 208 assertEquals(" [5, 6]", Strings.lenientFormat("", 5, 6)); 209 assertEquals("123", Strings.lenientFormat("%s%s%s", 1, 2, 3)); 210 assertEquals("1%s%s", Strings.lenientFormat("%s%s%s", 1)); 211 assertEquals("5 + 6 = 11", Strings.lenientFormat("%s + 6 = 11", 5)); 212 assertEquals("5 + 6 = 11", Strings.lenientFormat("5 + %s = 11", 6)); 213 assertEquals("5 + 6 = 11", Strings.lenientFormat("5 + 6 = %s", 11)); 214 assertEquals("5 + 6 = 11", Strings.lenientFormat("%s + %s = %s", 5, 6, 11)); 215 assertEquals("null [null, null]", Strings.lenientFormat("%s", null, null, null)); 216 assertEquals("null [5, 6]", Strings.lenientFormat(null, 5, 6)); 217 assertEquals("null", Strings.lenientFormat("%s", (Object) null)); 218 } 219 220 @J2ktIncompatible // TODO(b/319404022): Allow passing null array as varargs testLenientFormat_nullArrayVarargs()221 public void testLenientFormat_nullArrayVarargs() { 222 assertEquals("(Object[])null", Strings.lenientFormat("%s", (Object[]) null)); 223 } 224 225 @GwtIncompatible // GWT reflection includes less data testLenientFormat_badArgumentToString()226 public void testLenientFormat_badArgumentToString() { 227 assertThat(Strings.lenientFormat("boiler %s plate", new ThrowsOnToString())) 228 .matches( 229 // J2kt nested class name does not use "$" 230 "boiler <com\\.google\\.common\\.base\\.StringsTest[.$]ThrowsOnToString@[0-9a-f]+ " 231 + "threw java\\.lang\\.UnsupportedOperationException> plate"); 232 } 233 testLenientFormat_badArgumentToString_gwtFriendly()234 public void testLenientFormat_badArgumentToString_gwtFriendly() { 235 assertThat(Strings.lenientFormat("boiler %s plate", new ThrowsOnToString())) 236 .matches("boiler <.*> plate"); 237 } 238 239 private static class ThrowsOnToString { 240 @Override toString()241 public String toString() { 242 throw new UnsupportedOperationException(); 243 } 244 } 245 246 @J2ktIncompatible 247 @GwtIncompatible // NullPointerTester testNullPointers()248 public void testNullPointers() { 249 NullPointerTester tester = new NullPointerTester(); 250 tester.testAllPublicStaticMethods(Strings.class); 251 } 252 } 253