1 package com.fasterxml.jackson.annotation; 2 3 import com.fasterxml.jackson.annotation.JsonFormat.Feature; 4 import com.fasterxml.jackson.annotation.JsonFormat.Shape; 5 6 /** 7 * Tests to verify that it is possibly to merge {@link JsonFormat.Value} 8 * instances for overrides. 9 */ 10 public class FormatTest extends TestBase 11 { 12 private final JsonFormat.Value EMPTY = JsonFormat.Value.empty(); 13 14 @JsonFormat(shape=JsonFormat.Shape.BOOLEAN, pattern="xyz", timezone="bogus") 15 private final static class Bogus { } 16 testEmptyInstanceDefaults()17 public void testEmptyInstanceDefaults() { 18 JsonFormat.Value empty = JsonFormat.Value.empty(); 19 for (Feature f : Feature.values()) { 20 assertNull(empty.getFeature(f)); 21 } 22 assertFalse(empty.hasLocale()); 23 assertFalse(empty.hasPattern()); 24 assertFalse(empty.hasShape()); 25 assertFalse(empty.hasTimeZone()); 26 assertFalse(empty.hasLenient()); 27 28 assertFalse(empty.isLenient()); 29 } 30 testEquality()31 public void testEquality() { 32 assertTrue(EMPTY.equals(EMPTY)); 33 assertTrue(new JsonFormat.Value().equals(new JsonFormat.Value())); 34 35 JsonFormat.Value v1 = JsonFormat.Value.forShape(Shape.BOOLEAN); 36 JsonFormat.Value v2 = JsonFormat.Value.forShape(Shape.BOOLEAN); 37 JsonFormat.Value v3 = JsonFormat.Value.forShape(Shape.SCALAR); 38 39 assertTrue(v1.equals(v2)); 40 assertTrue(v2.equals(v1)); 41 42 assertFalse(v1.equals(v3)); 43 assertFalse(v3.equals(v1)); 44 assertFalse(v2.equals(v3)); 45 assertFalse(v3.equals(v2)); 46 47 // not strictly guaranteed but... 48 assertFalse(v1.hashCode() == v3.hashCode()); 49 50 // then let's converge 51 assertEquals(v1, v3.withShape(Shape.BOOLEAN)); 52 assertFalse(v1.equals(v1.withPattern("ZBC"))); 53 assertFalse(v1.equals(v1.withFeature(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY))); 54 assertFalse(v1.equals(v1.withoutFeature(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY))); 55 } 56 testToString()57 public void testToString() { 58 assertEquals("JsonFormat.Value(pattern=,shape=STRING,lenient=null,locale=null,timezone=null,features=EMPTY)", 59 JsonFormat.Value.forShape(JsonFormat.Shape.STRING).toString()); 60 assertEquals("JsonFormat.Value(pattern=[.],shape=ANY,lenient=null,locale=null,timezone=null,features=EMPTY)", 61 JsonFormat.Value.forPattern("[.]").toString()); 62 } 63 testFromAnnotation()64 public void testFromAnnotation() 65 { 66 JsonFormat ann = Bogus.class.getAnnotation(JsonFormat.class); 67 JsonFormat.Value v = JsonFormat.Value.from(ann); 68 assertEquals("xyz", v.getPattern()); 69 assertEquals(JsonFormat.Shape.BOOLEAN, v.getShape()); 70 // note: since it's not valid, should not try access as real thing 71 assertEquals("bogus", v.timeZoneAsString()); 72 73 // also: 74 assertSame(EMPTY, JsonFormat.Value.from(null)); 75 } 76 testSimpleMerge()77 public void testSimpleMerge() 78 { 79 // Start with an empty instance 80 assertFalse(EMPTY.hasLocale()); 81 assertFalse(EMPTY.hasPattern()); 82 assertFalse(EMPTY.hasShape()); 83 assertFalse(EMPTY.hasTimeZone()); 84 85 assertNull(EMPTY.getLocale()); 86 87 // then with a non-empty one 88 final String TEST_PATTERN = "format-string"; // not parsed, usage varies 89 90 JsonFormat.Value v = JsonFormat.Value.forPattern(TEST_PATTERN); 91 assertTrue(v.hasPattern()); 92 assertEquals(TEST_PATTERN, v.getPattern()); 93 assertFalse(v.hasLocale()); 94 assertFalse(v.hasShape()); 95 assertFalse(v.hasTimeZone()); 96 97 // and ensure nothing overridden with empty 98 JsonFormat.Value merged = v.withOverrides(EMPTY); 99 assertEquals(TEST_PATTERN, merged.getPattern()); 100 assertFalse(merged.hasLocale()); 101 assertFalse(merged.hasShape()); 102 assertFalse(merged.hasTimeZone()); 103 104 // minor optimization: overriding with itself has no effect 105 assertSame(merged, merged.withOverrides(merged)); 106 107 // but that empty is overridden 108 merged = JsonFormat.Value.merge(EMPTY, v); 109 assertEquals(TEST_PATTERN, merged.getPattern()); 110 assertFalse(merged.hasLocale()); 111 assertFalse(merged.hasShape()); 112 assertFalse(merged.hasTimeZone()); 113 114 // also some shortcuts: 115 assertSame(merged, merged.withOverrides(null)); 116 117 // then with some other combinations 118 final JsonFormat.Shape TEST_SHAPE = JsonFormat.Shape.NUMBER; 119 JsonFormat.Value v2 = JsonFormat.Value.forShape(TEST_SHAPE); 120 121 merged = v.withOverrides(v2); 122 assertEquals(TEST_PATTERN, merged.getPattern()); 123 assertFalse(merged.hasLocale()); 124 assertEquals(TEST_SHAPE, merged.getShape()); 125 assertFalse(merged.hasTimeZone()); 126 127 merged = v2.withOverrides(v); 128 assertEquals(TEST_PATTERN, merged.getPattern()); 129 assertFalse(merged.hasLocale()); 130 assertEquals(TEST_SHAPE, merged.getShape()); 131 assertFalse(merged.hasTimeZone()); 132 } 133 testMultiMerge()134 public void testMultiMerge() 135 { 136 final String TEST_PATTERN = "format-string"; // not parsed, usage varies 137 JsonFormat.Value format2 = JsonFormat.Value.forPattern(TEST_PATTERN); 138 JsonFormat.Value format3 = JsonFormat.Value.forLeniency(Boolean.FALSE); 139 140 JsonFormat.Value merged = JsonFormat.Value.mergeAll(EMPTY, format2, format3); 141 assertEquals(TEST_PATTERN, merged.getPattern()); 142 assertEquals(Boolean.FALSE, merged.getLenient()); 143 } 144 145 /* 146 /********************************************************** 147 /* Test specific value properties 148 /********************************************************** 149 */ 150 testLeniency()151 public void testLeniency() { 152 JsonFormat.Value empty = JsonFormat.Value.empty(); 153 assertFalse(empty.hasLenient()); 154 assertFalse(empty.isLenient()); 155 assertNull(empty.getLenient()); 156 157 JsonFormat.Value lenient = empty.withLenient(Boolean.TRUE); 158 assertTrue(lenient.hasLenient()); 159 assertTrue(lenient.isLenient()); 160 assertEquals(Boolean.TRUE, lenient.getLenient()); 161 assertTrue(lenient.equals(lenient)); 162 assertFalse(empty.equals(lenient)); 163 assertFalse(lenient.equals(empty)); 164 165 // should NOT create now one if no change: 166 assertSame(lenient, lenient.withLenient(Boolean.TRUE)); 167 168 JsonFormat.Value strict = lenient.withLenient(Boolean.FALSE); 169 assertTrue(strict.hasLenient()); 170 assertFalse(strict.isLenient()); 171 assertEquals(Boolean.FALSE, strict.getLenient()); 172 assertTrue(strict.equals(strict)); 173 assertFalse(empty.equals(strict)); 174 assertFalse(strict.equals(empty)); 175 assertFalse(lenient.equals(strict)); 176 assertFalse(strict.equals(lenient)); 177 178 // and finally, can also clear up setting 179 JsonFormat.Value dunno = lenient.withLenient(null); 180 assertFalse(dunno.hasLenient()); 181 assertFalse(dunno.isLenient()); 182 assertNull(dunno.getLenient()); 183 assertTrue(empty.equals(dunno)); 184 assertTrue(dunno.equals(empty)); 185 assertFalse(lenient.equals(dunno)); 186 assertFalse(dunno.equals(lenient)); 187 } 188 testCaseInsensitiveValues()189 public void testCaseInsensitiveValues() { 190 JsonFormat.Value empty = JsonFormat.Value.empty(); 191 assertNull(empty.getFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES)); 192 193 JsonFormat.Value insensitive = empty.withFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES); 194 assertTrue(insensitive.getFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES)); 195 196 JsonFormat.Value sensitive = empty.withoutFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES); 197 assertFalse(sensitive.getFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES)); 198 } 199 testShape()200 public void testShape() { 201 assertFalse(JsonFormat.Shape.STRING.isNumeric()); 202 assertFalse(JsonFormat.Shape.STRING.isStructured()); 203 204 assertTrue(JsonFormat.Shape.NUMBER_INT.isNumeric()); 205 assertTrue(JsonFormat.Shape.NUMBER_FLOAT.isNumeric()); 206 assertTrue(JsonFormat.Shape.NUMBER.isNumeric()); 207 208 assertTrue(JsonFormat.Shape.ARRAY.isStructured()); 209 assertTrue(JsonFormat.Shape.OBJECT.isStructured()); 210 } 211 testFeatures()212 public void testFeatures() { 213 JsonFormat.Features f1 = JsonFormat.Features.empty(); 214 JsonFormat.Features f2 = f1.with(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 215 .without(Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS); 216 assertTrue(f1.equals(f1)); 217 assertFalse(f1.equals(f2)); 218 assertFalse(f1.equals(null)); 219 assertFalse(f1.equals("foo")); 220 221 assertNull(f1.get(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); 222 assertEquals(Boolean.TRUE, f2.get(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); 223 224 assertNull(f1.get(Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)); 225 assertEquals(Boolean.FALSE, f2.get(Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)); 226 227 JsonFormat.Features f3 = f1.withOverrides(f2); 228 assertEquals(Boolean.TRUE, f3.get(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); 229 assertEquals(Boolean.FALSE, f3.get(Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)); 230 231 // switch values around 232 JsonFormat.Features f4 = JsonFormat.Features.construct( 233 new Feature[] { // enabled: 234 Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS 235 }, new Feature[] { // enabled 236 Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY 237 }); 238 assertEquals(Boolean.FALSE, f4.get(Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)); 239 assertEquals(Boolean.TRUE, f4.get(Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)); 240 } 241 } 242