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