1 /* 2 * Copyright (C) 2009 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 21 import com.google.common.annotations.GwtCompatible; 22 import com.google.common.annotations.GwtIncompatible; 23 import com.google.common.collect.ImmutableMap; 24 import java.util.Arrays; 25 import java.util.Map; 26 import junit.framework.TestCase; 27 28 /** 29 * Tests for {@link MoreObjects#toStringHelper(Object)}. 30 * 31 * @author Jason Lee 32 */ 33 @GwtCompatible 34 public class ToStringHelperTest extends TestCase { 35 36 @GwtIncompatible // Class names are obfuscated in GWT testConstructor_instance()37 public void testConstructor_instance() { 38 String toTest = MoreObjects.toStringHelper(this).toString(); 39 assertEquals("ToStringHelperTest{}", toTest); 40 } 41 testConstructorLenient_instance()42 public void testConstructorLenient_instance() { 43 String toTest = MoreObjects.toStringHelper(this).toString(); 44 assertTrue(toTest, toTest.matches(".*\\{\\}")); 45 } 46 47 @GwtIncompatible // Class names are obfuscated in GWT testConstructor_innerClass()48 public void testConstructor_innerClass() { 49 String toTest = MoreObjects.toStringHelper(new TestClass()).toString(); 50 assertEquals("TestClass{}", toTest); 51 } 52 testConstructorLenient_innerClass()53 public void testConstructorLenient_innerClass() { 54 String toTest = MoreObjects.toStringHelper(new TestClass()).toString(); 55 assertTrue(toTest, toTest.matches(".*\\{\\}")); 56 } 57 58 @GwtIncompatible // Class names are obfuscated in GWT testConstructor_anonymousClass()59 public void testConstructor_anonymousClass() { 60 String toTest = MoreObjects.toStringHelper(new Object() {}).toString(); 61 assertEquals("{}", toTest); 62 } 63 testConstructorLenient_anonymousClass()64 public void testConstructorLenient_anonymousClass() { 65 String toTest = MoreObjects.toStringHelper(new Object() {}).toString(); 66 assertTrue(toTest, toTest.matches(".*\\{\\}")); 67 } 68 69 @GwtIncompatible // Class names are obfuscated in GWT testConstructor_classObject()70 public void testConstructor_classObject() { 71 String toTest = MoreObjects.toStringHelper(TestClass.class).toString(); 72 assertEquals("TestClass{}", toTest); 73 } 74 testConstructorLenient_classObject()75 public void testConstructorLenient_classObject() { 76 String toTest = MoreObjects.toStringHelper(TestClass.class).toString(); 77 assertTrue(toTest, toTest.matches(".*\\{\\}")); 78 } 79 testConstructor_stringObject()80 public void testConstructor_stringObject() { 81 String toTest = MoreObjects.toStringHelper("FooBar").toString(); 82 assertEquals("FooBar{}", toTest); 83 } 84 85 @GwtIncompatible // Class names are obfuscated in GWT testToStringHelper_localInnerClass()86 public void testToStringHelper_localInnerClass() { 87 // Local inner classes have names ending like "Outer.$1Inner" 88 class LocalInnerClass {} 89 String toTest = MoreObjects.toStringHelper(new LocalInnerClass()).toString(); 90 assertEquals("LocalInnerClass{}", toTest); 91 } 92 testToStringHelperLenient_localInnerClass()93 public void testToStringHelperLenient_localInnerClass() { 94 class LocalInnerClass {} 95 String toTest = MoreObjects.toStringHelper(new LocalInnerClass()).toString(); 96 assertTrue(toTest, toTest.matches(".*\\{\\}")); 97 } 98 99 @GwtIncompatible // Class names are obfuscated in GWT testToStringHelper_localInnerNestedClass()100 public void testToStringHelper_localInnerNestedClass() { 101 class LocalInnerClass { 102 class LocalInnerNestedClass {} 103 } 104 String toTest = 105 MoreObjects.toStringHelper(new LocalInnerClass().new LocalInnerNestedClass()).toString(); 106 assertEquals("LocalInnerNestedClass{}", toTest); 107 } 108 testToStringHelperLenient_localInnerNestedClass()109 public void testToStringHelperLenient_localInnerNestedClass() { 110 class LocalInnerClass { 111 class LocalInnerNestedClass {} 112 } 113 String toTest = 114 MoreObjects.toStringHelper(new LocalInnerClass().new LocalInnerNestedClass()).toString(); 115 assertTrue(toTest, toTest.matches(".*\\{\\}")); 116 } 117 118 @GwtIncompatible // Class names are obfuscated in GWT testToStringHelper_moreThanNineAnonymousClasses()119 public void testToStringHelper_moreThanNineAnonymousClasses() { 120 // The nth anonymous class has a name ending like "Outer.$n" 121 Object unused1 = new Object() {}; 122 Object unused2 = new Object() {}; 123 Object unused3 = new Object() {}; 124 Object unused4 = new Object() {}; 125 Object unused5 = new Object() {}; 126 Object unused6 = new Object() {}; 127 Object unused7 = new Object() {}; 128 Object unused8 = new Object() {}; 129 Object unused9 = new Object() {}; 130 Object o10 = new Object() {}; 131 String toTest = MoreObjects.toStringHelper(o10).toString(); 132 assertEquals("{}", toTest); 133 } 134 testToStringHelperLenient_moreThanNineAnonymousClasses()135 public void testToStringHelperLenient_moreThanNineAnonymousClasses() { 136 // The nth anonymous class has a name ending like "Outer.$n" 137 Object unused1 = new Object() {}; 138 Object unused2 = new Object() {}; 139 Object unused3 = new Object() {}; 140 Object unused4 = new Object() {}; 141 Object unused5 = new Object() {}; 142 Object unused6 = new Object() {}; 143 Object unused7 = new Object() {}; 144 Object unused8 = new Object() {}; 145 Object unused9 = new Object() {}; 146 Object o10 = new Object() {}; 147 String toTest = MoreObjects.toStringHelper(o10).toString(); 148 assertTrue(toTest, toTest.matches(".*\\{\\}")); 149 } 150 151 // all remaining test are on an inner class with various fields 152 @GwtIncompatible // Class names are obfuscated in GWT testToString_oneField()153 public void testToString_oneField() { 154 String toTest = MoreObjects.toStringHelper(new TestClass()).add("field1", "Hello").toString(); 155 assertEquals("TestClass{field1=Hello}", toTest); 156 } 157 158 @GwtIncompatible // Class names are obfuscated in GWT testToString_oneIntegerField()159 public void testToString_oneIntegerField() { 160 String toTest = 161 MoreObjects.toStringHelper(new TestClass()).add("field1", Integer.valueOf(42)).toString(); 162 assertEquals("TestClass{field1=42}", toTest); 163 } 164 165 @GwtIncompatible // Class names are obfuscated in GWT testToString_nullInteger()166 public void testToString_nullInteger() { 167 String toTest = 168 MoreObjects.toStringHelper(new TestClass()).add("field1", (Integer) null).toString(); 169 assertEquals("TestClass{field1=null}", toTest); 170 } 171 testToStringLenient_oneField()172 public void testToStringLenient_oneField() { 173 String toTest = MoreObjects.toStringHelper(new TestClass()).add("field1", "Hello").toString(); 174 assertTrue(toTest, toTest.matches(".*\\{field1\\=Hello\\}")); 175 } 176 testToStringLenient_oneIntegerField()177 public void testToStringLenient_oneIntegerField() { 178 String toTest = 179 MoreObjects.toStringHelper(new TestClass()).add("field1", Integer.valueOf(42)).toString(); 180 assertTrue(toTest, toTest.matches(".*\\{field1\\=42\\}")); 181 } 182 testToStringLenient_nullInteger()183 public void testToStringLenient_nullInteger() { 184 String toTest = 185 MoreObjects.toStringHelper(new TestClass()).add("field1", (Integer) null).toString(); 186 assertTrue(toTest, toTest.matches(".*\\{field1\\=null\\}")); 187 } 188 189 @GwtIncompatible // Class names are obfuscated in GWT testToString_complexFields()190 public void testToString_complexFields() { 191 Map<String, Integer> map = 192 ImmutableMap.<String, Integer>builder().put("abc", 1).put("def", 2).put("ghi", 3).build(); 193 String toTest = 194 MoreObjects.toStringHelper(new TestClass()) 195 .add("field1", "This is string.") 196 .add("field2", Arrays.asList("abc", "def", "ghi")) 197 .add("field3", map) 198 .toString(); 199 final String expected = 200 "TestClass{" 201 + "field1=This is string., field2=[abc, def, ghi], field3={abc=1, def=2, ghi=3}}"; 202 203 assertEquals(expected, toTest); 204 } 205 testToStringLenient_complexFields()206 public void testToStringLenient_complexFields() { 207 Map<String, Integer> map = 208 ImmutableMap.<String, Integer>builder().put("abc", 1).put("def", 2).put("ghi", 3).build(); 209 String toTest = 210 MoreObjects.toStringHelper(new TestClass()) 211 .add("field1", "This is string.") 212 .add("field2", Arrays.asList("abc", "def", "ghi")) 213 .add("field3", map) 214 .toString(); 215 final String expectedRegex = 216 ".*\\{" 217 + "field1\\=This is string\\., " 218 + "field2\\=\\[abc, def, ghi\\], " 219 + "field3=\\{abc\\=1, def\\=2, ghi\\=3\\}\\}"; 220 221 assertTrue(toTest, toTest.matches(expectedRegex)); 222 } 223 testToString_addWithNullName()224 public void testToString_addWithNullName() { 225 MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(new TestClass()); 226 assertThrows(NullPointerException.class, () -> helper.add(null, "Hello")); 227 } 228 229 @GwtIncompatible // Class names are obfuscated in GWT testToString_addWithNullValue()230 public void testToString_addWithNullValue() { 231 final String result = MoreObjects.toStringHelper(new TestClass()).add("Hello", null).toString(); 232 233 assertEquals("TestClass{Hello=null}", result); 234 } 235 testToStringLenient_addWithNullValue()236 public void testToStringLenient_addWithNullValue() { 237 final String result = MoreObjects.toStringHelper(new TestClass()).add("Hello", null).toString(); 238 assertTrue(result, result.matches(".*\\{Hello\\=null\\}")); 239 } 240 241 @GwtIncompatible // Class names are obfuscated in GWT testToString_toStringTwice()242 public void testToString_toStringTwice() { 243 MoreObjects.ToStringHelper helper = 244 MoreObjects.toStringHelper(new TestClass()) 245 .add("field1", 1) 246 .addValue("value1") 247 .add("field2", "value2"); 248 final String expected = "TestClass{field1=1, value1, field2=value2}"; 249 250 assertEquals(expected, helper.toString()); 251 // Call toString again 252 assertEquals(expected, helper.toString()); 253 254 // Make sure the cached value is reset when we modify the helper at all 255 final String expected2 = "TestClass{field1=1, value1, field2=value2, 2}"; 256 helper.addValue(2); 257 assertEquals(expected2, helper.toString()); 258 } 259 260 @GwtIncompatible // Class names are obfuscated in GWT testToString_addValue()261 public void testToString_addValue() { 262 String toTest = 263 MoreObjects.toStringHelper(new TestClass()) 264 .add("field1", 1) 265 .addValue("value1") 266 .add("field2", "value2") 267 .addValue(2) 268 .toString(); 269 final String expected = "TestClass{field1=1, value1, field2=value2, 2}"; 270 271 assertEquals(expected, toTest); 272 } 273 testToStringLenient_addValue()274 public void testToStringLenient_addValue() { 275 String toTest = 276 MoreObjects.toStringHelper(new TestClass()) 277 .add("field1", 1) 278 .addValue("value1") 279 .add("field2", "value2") 280 .addValue(2) 281 .toString(); 282 final String expected = ".*\\{field1\\=1, value1, field2\\=value2, 2\\}"; 283 284 assertTrue(toTest, toTest.matches(expected)); 285 } 286 287 @GwtIncompatible // Class names are obfuscated in GWT testToString_addValueWithNullValue()288 public void testToString_addValueWithNullValue() { 289 final String result = 290 MoreObjects.toStringHelper(new TestClass()) 291 .addValue(null) 292 .addValue("Hello") 293 .addValue(null) 294 .toString(); 295 final String expected = "TestClass{null, Hello, null}"; 296 297 assertEquals(expected, result); 298 } 299 testToStringLenient_addValueWithNullValue()300 public void testToStringLenient_addValueWithNullValue() { 301 final String result = 302 MoreObjects.toStringHelper(new TestClass()) 303 .addValue(null) 304 .addValue("Hello") 305 .addValue(null) 306 .toString(); 307 final String expected = ".*\\{null, Hello, null\\}"; 308 309 assertTrue(result, result.matches(expected)); 310 } 311 312 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_oneField()313 public void testToStringOmitNullValues_oneField() { 314 String toTest = 315 MoreObjects.toStringHelper(new TestClass()).omitNullValues().add("field1", null).toString(); 316 assertEquals("TestClass{}", toTest); 317 } 318 319 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_manyFieldsFirstNull()320 public void testToStringOmitNullValues_manyFieldsFirstNull() { 321 String toTest = 322 MoreObjects.toStringHelper(new TestClass()) 323 .omitNullValues() 324 .add("field1", null) 325 .add("field2", "Googley") 326 .add("field3", "World") 327 .toString(); 328 assertEquals("TestClass{field2=Googley, field3=World}", toTest); 329 } 330 331 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_manyFieldsOmitAfterNull()332 public void testToStringOmitNullValues_manyFieldsOmitAfterNull() { 333 String toTest = 334 MoreObjects.toStringHelper(new TestClass()) 335 .add("field1", null) 336 .add("field2", "Googley") 337 .add("field3", "World") 338 .omitNullValues() 339 .toString(); 340 assertEquals("TestClass{field2=Googley, field3=World}", toTest); 341 } 342 343 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_manyFieldsLastNull()344 public void testToStringOmitNullValues_manyFieldsLastNull() { 345 String toTest = 346 MoreObjects.toStringHelper(new TestClass()) 347 .omitNullValues() 348 .add("field1", "Hello") 349 .add("field2", "Googley") 350 .add("field3", null) 351 .toString(); 352 assertEquals("TestClass{field1=Hello, field2=Googley}", toTest); 353 } 354 355 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitEmptyValues_oneValue()356 public void testToStringOmitEmptyValues_oneValue() { 357 String toTest = 358 MoreObjects.toStringHelper(new TestClass()).omitNullValues().addValue(null).toString(); 359 assertEquals("TestClass{}", toTest); 360 } 361 362 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_manyValuesFirstNull()363 public void testToStringOmitNullValues_manyValuesFirstNull() { 364 String toTest = 365 MoreObjects.toStringHelper(new TestClass()) 366 .omitNullValues() 367 .addValue(null) 368 .addValue("Googley") 369 .addValue("World") 370 .toString(); 371 assertEquals("TestClass{Googley, World}", toTest); 372 } 373 374 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_manyValuesLastNull()375 public void testToStringOmitNullValues_manyValuesLastNull() { 376 String toTest = 377 MoreObjects.toStringHelper(new TestClass()) 378 .omitNullValues() 379 .addValue("Hello") 380 .addValue("Googley") 381 .addValue(null) 382 .toString(); 383 assertEquals("TestClass{Hello, Googley}", toTest); 384 } 385 386 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_differentOrder()387 public void testToStringOmitNullValues_differentOrder() { 388 String expected = "TestClass{field1=Hello, field2=Googley, field3=World}"; 389 String toTest1 = 390 MoreObjects.toStringHelper(new TestClass()) 391 .omitNullValues() 392 .add("field1", "Hello") 393 .add("field2", "Googley") 394 .add("field3", "World") 395 .toString(); 396 String toTest2 = 397 MoreObjects.toStringHelper(new TestClass()) 398 .add("field1", "Hello") 399 .add("field2", "Googley") 400 .omitNullValues() 401 .add("field3", "World") 402 .toString(); 403 assertEquals(expected, toTest1); 404 assertEquals(expected, toTest2); 405 } 406 407 @GwtIncompatible // Class names are obfuscated in GWT testToStringOmitNullValues_canBeCalledManyTimes()408 public void testToStringOmitNullValues_canBeCalledManyTimes() { 409 String toTest = 410 MoreObjects.toStringHelper(new TestClass()) 411 .omitNullValues() 412 .omitNullValues() 413 .add("field1", "Hello") 414 .omitNullValues() 415 .add("field2", "Googley") 416 .omitNullValues() 417 .add("field3", "World") 418 .toString(); 419 assertEquals("TestClass{field1=Hello, field2=Googley, field3=World}", toTest); 420 } 421 testToStringHelperWithArrays()422 public void testToStringHelperWithArrays() { 423 String[] strings = {"hello", "world"}; 424 int[] ints = {2, 42}; 425 Object[] objects = {"obj"}; 426 String[] arrayWithNull = {null}; 427 Object[] empty = {}; 428 String toTest = 429 MoreObjects.toStringHelper("TSH") 430 .add("strings", strings) 431 .add("ints", ints) 432 .add("objects", objects) 433 .add("arrayWithNull", arrayWithNull) 434 .add("empty", empty) 435 .toString(); 436 assertEquals( 437 "TSH{strings=[hello, world], ints=[2, 42], objects=[obj], arrayWithNull=[null], empty=[]}", 438 toTest); 439 } 440 441 /** Test class for testing formatting of inner classes. */ 442 private static class TestClass {} 443 } 444