001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.i18n; 017 018import static org.hamcrest.core.Is.is; 019import static org.hamcrest.core.IsInstanceOf.instanceOf; 020import static org.hamcrest.core.IsNot.not; 021import static org.hamcrest.core.IsNull.notNullValue; 022import static org.hamcrest.core.IsNull.nullValue; 023import static org.junit.Assert.assertThat; 024import java.lang.reflect.Field; 025import java.lang.reflect.Modifier; 026import java.util.Iterator; 027import java.util.Locale; 028import java.util.Map; 029import java.util.Set; 030import java.util.Map.Entry; 031import org.junit.Before; 032import org.junit.BeforeClass; 033import org.junit.Test; 034import org.modeshape.common.CommonI18n; 035import org.modeshape.common.SystemFailureException; 036 037/** 038 * @author John Verhaeg 039 * @author Randall Hauch 040 */ 041public final class I18nTest { 042 043 @BeforeClass 044 public static void beforeClass() { 045 Locale.setDefault(Locale.US); 046 } 047 048 @Before 049 public void beforeEach() throws Exception { 050 clearFields(TestI18n.class); 051 clearFields(TestI18nDuplicateProperty.class); 052 clearFields(TestI18nFinal.class); 053 clearFields(TestI18nFinalField.class); 054 clearFields(TestI18nInterface.class); 055 clearFields(TestI18nMissingLocalization.class); 056 clearFields(TestI18nMissingProperty.class); 057 clearFields(TestI18nNotPublicField.class); 058 clearFields(TestI18nNotStaticField.class); 059 clearFields(TestI18nPrivate.class); 060 clearFields(TestI18nUnusedProperty.class); 061 for (Entry<Locale, Map<Class<?>, Set<String>>> localeToMapEntry : I18n.LOCALE_TO_CLASS_TO_PROBLEMS_MAP.entrySet()) { 062 for (Iterator<Entry<Class<?>, Set<String>>> iter = localeToMapEntry.getValue().entrySet().iterator(); iter.hasNext();) { 063 if (iter.next().getKey() != CommonI18n.class) { 064 iter.remove(); 065 } 066 } 067 } 068 } 069 070 private void clearFields( Class<?> i18nClass ) throws Exception { 071 for (Field fld : i18nClass.getDeclaredFields()) { 072 if (fld.getType() == I18n.class && (fld.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC 073 && (fld.getModifiers() & Modifier.STATIC) == Modifier.STATIC 074 && (fld.getModifiers() & Modifier.FINAL) != Modifier.FINAL) { 075 fld.set(null, null); 076 } 077 } 078 } 079 080 @Test( expected = IllegalArgumentException.class ) 081 public void shouldFailToGetLocalizationProblemLocalesIfNoClassSupplied() { 082 I18n.getLocalizationProblemLocales(null); 083 } 084 085 @Test 086 public void shouldNeverReturnNullWhenGettingLocalizationProblemLocales() { 087 assertThat(I18n.getLocalizationProblemLocales(TestI18n.class), notNullValue()); 088 } 089 090 @Test( expected = IllegalArgumentException.class ) 091 public void shouldFailToGetLocalizationProblemsForDefaultLocaleIfNoClassSupplied() { 092 I18n.getLocalizationProblems(null); 093 } 094 095 @Test( expected = IllegalArgumentException.class ) 096 public void shouldFailToGetLocalizationProblemsForSuppliedLocaleIfNoClassSupplied() { 097 I18n.getLocalizationProblems(null, Locale.US); 098 } 099 100 @Test 101 public void shouldNeverReturnNullWhenGettingLocalizationProblemsForDefaultLocale() { 102 assertThat(I18n.getLocalizationProblems(TestI18n.class), notNullValue()); 103 } 104 105 @Test 106 public void shouldNeverReturnNullWhenGettingLocalizationProblemsForSuppliedLocale() { 107 assertThat(I18n.getLocalizationProblems(TestI18n.class, Locale.US), notNullValue()); 108 } 109 110 @Test 111 public void shouldNotHaveLocalizationProblemsAfterInitializationButBeforeLocalization() { 112 I18n.initialize(TestI18nUnusedProperty.class); 113 assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class, null).isEmpty(), is(true)); 114 assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).isEmpty(), is(true)); 115 } 116 117 @Test 118 public void shouldGetLocalizationProblemsForDefaultLocaleIfNoLocaleSupplied() { 119 I18n.initialize(TestI18nUnusedProperty.class); 120 TestI18nUnusedProperty.testMessage.text("test"); 121 assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class, null).isEmpty(), is(false)); 122 } 123 124 @Test( expected = IllegalArgumentException.class ) 125 public void shouldFailToInitializeIfNoClassSupplied() { 126 I18n.initialize(null); 127 } 128 129 @Test( expected = SystemFailureException.class ) 130 public void shouldFailToInitializeFinalI18nField() { 131 try { 132 I18n.initialize(TestI18nFinalField.class); 133 } catch (SystemFailureException err) { 134 assertThat(err.getMessage(), is(CommonI18n.i18nFieldFinal.text("testMessage", TestI18nFinalField.class))); 135 System.err.println(err); 136 throw err; 137 } 138 } 139 140 @Test( expected = SystemFailureException.class ) 141 public void shouldFailToInitializeNonPublicI18nField() { 142 try { 143 I18n.initialize(TestI18nNotPublicField.class); 144 } catch (SystemFailureException err) { 145 assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotPublic.text("testMessage", TestI18nNotPublicField.class))); 146 System.err.println(err); 147 throw err; 148 } 149 } 150 151 @Test( expected = SystemFailureException.class ) 152 public void shouldFailToInitializeNonStaticI18nField() { 153 try { 154 I18n.initialize(TestI18nNotStaticField.class); 155 } catch (SystemFailureException err) { 156 assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotStatic.text("testMessage", TestI18nNotStaticField.class))); 157 System.err.println(err); 158 throw err; 159 } 160 } 161 162 @Test 163 public void shouldInitializeFinalClasses() { 164 I18n.initialize(TestI18nFinal.class); 165 assertThat(TestI18nFinal.testMessage, instanceOf(I18n.class)); 166 } 167 168 @Test 169 public void shouldInitializePrivateClasses() { 170 I18n.initialize(TestI18nPrivate.class); 171 assertThat(TestI18nPrivate.testMessage, instanceOf(I18n.class)); 172 } 173 174 @Test 175 public void shouldInitializeI18nFields() { 176 I18n.initialize(TestI18n.class); 177 assertThat(TestI18n.testMessage, instanceOf(I18n.class)); 178 } 179 180 @Test 181 public void shouldNotInitializeNonI18nFields() { 182 I18n.initialize(TestI18n.class); 183 assertThat(TestI18n.nonI18n, nullValue()); 184 } 185 186 @Test( expected = IllegalArgumentException.class ) 187 public void shouldFailToInitializeInterfaces() { 188 try { 189 I18n.initialize(TestI18nInterface.class); 190 } catch (IllegalArgumentException err) { 191 assertThat(err.getMessage(), is(CommonI18n.i18nClassInterface.text(TestI18nInterface.class.getName()))); 192 System.err.println(err); 193 throw err; 194 } 195 } 196 197 @Test 198 public void shouldProvideIdempotentInitialization() { 199 I18n.initialize(TestI18n.class); 200 assertThat(TestI18n.testMessage1.text("test"), is("test")); 201 I18n.initialize(TestI18n.class); 202 assertThat(TestI18n.testMessage1.text("test"), is("test")); 203 } 204 205 @Test 206 public void shouldNotBeLocalizedAfterInitialization() { 207 I18n.initialize(TestI18nDuplicateProperty.class); 208 assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), nullValue()); 209 assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), nullValue()); 210 } 211 212 @Test 213 public void shouldHaveIdThatMatchesFieldName() { 214 I18n.initialize(TestI18n.class); 215 assertThat(TestI18n.testMessage.id(), is("testMessage")); 216 } 217 218 @Test 219 public void shouldNotBeLocalizedIfAskedForId() { 220 I18n.initialize(TestI18nDuplicateProperty.class); 221 TestI18nDuplicateProperty.testMessage.id(); 222 assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), nullValue()); 223 assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), nullValue()); 224 } 225 226 @Test 227 public void shouldBeLocalizedIfAskedIfHasProblem() { 228 I18n.initialize(TestI18nDuplicateProperty.class); 229 TestI18nDuplicateProperty.testMessage.hasProblem(); 230 assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue()); 231 assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue()); 232 } 233 234 @Test 235 public void shouldBeLocalizedIfAskedForProblem() { 236 I18n.initialize(TestI18nDuplicateProperty.class); 237 TestI18nDuplicateProperty.testMessage.problem(); 238 assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue()); 239 assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue()); 240 } 241 242 @Test 243 public void shouldBeLocalizedIfConvertedToString() { 244 I18n.initialize(TestI18nDuplicateProperty.class); 245 TestI18nDuplicateProperty.testMessage.toString(); 246 assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue()); 247 assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue()); 248 } 249 250 @Test 251 public void shouldContainAngleBracketedProblemInTextIfMissingLocalization() { 252 I18n.initialize(TestI18nMissingLocalization.class); 253 String text = TestI18nMissingLocalization.testMessage.text(); 254 assertThat(text, 255 is('<' + CommonI18n.i18nLocalizationProblems.text(TestI18nMissingLocalization.class, Locale.getDefault()) + '>')); 256 System.out.println("Text: " + text); 257 } 258 259 @Test 260 public void shouldHaveProblemIfMissingLocalization() { 261 I18n.initialize(TestI18nMissingLocalization.class); 262 assertThat(TestI18nMissingLocalization.testMessage.hasProblem(), is(true)); 263 String problem = TestI18nMissingLocalization.testMessage.problem(); 264 assertThat(problem, is(CommonI18n.i18nLocalizationProblems.text(TestI18nMissingLocalization.class, Locale.getDefault()))); 265 System.out.println("Problem: " + problem); 266 } 267 268 @Test 269 public void shouldHaveLocalicationProblemIfMissingLocalization() { 270 I18n.initialize(TestI18nMissingLocalization.class); 271 TestI18nMissingLocalization.testMessage.text(); 272 assertThat(I18n.getLocalizationProblems(TestI18nMissingLocalization.class).size(), is(1)); 273 assertThat(I18n.getLocalizationProblems(TestI18nMissingLocalization.class).iterator().next(), 274 is(CommonI18n.i18nLocalizationFileNotFound.text(TestI18nMissingLocalization.class.getName()))); 275 assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingLocalization.class).size(), is(1)); 276 assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingLocalization.class).iterator().next(), 277 is(Locale.getDefault())); 278 } 279 280 @Test 281 public void shouldHaveTextIfPropertyDuplicate() { 282 I18n.initialize(TestI18nDuplicateProperty.class); 283 String text = TestI18nDuplicateProperty.testMessage.text("test"); 284 assertThat(text.charAt(0), not('<')); 285 System.out.println("Text: " + text); 286 } 287 288 @Test 289 public void shouldHaveProblemIfPropertyDuplicate() { 290 I18n.initialize(TestI18nDuplicateProperty.class); 291 assertThat(TestI18nDuplicateProperty.testMessage.hasProblem(), is(true)); 292 String problem = TestI18nDuplicateProperty.testMessage.problem(); 293 assertThat(problem, notNullValue()); 294 System.out.println("Problem: " + problem); 295 } 296 297 @Test 298 public void shouldNotHaveLocalicationProblemIfPropertyDuplicate() { 299 I18n.initialize(TestI18nDuplicateProperty.class); 300 TestI18nDuplicateProperty.testMessage.text("test"); 301 assertThat(I18n.getLocalizationProblems(TestI18nDuplicateProperty.class).isEmpty(), is(true)); 302 assertThat(I18n.getLocalizationProblemLocales(TestI18nDuplicateProperty.class).isEmpty(), is(true)); 303 } 304 305 @Test 306 public void shouldContainAngleBracketedProblemInTextIfPropertyMissing() { 307 I18n.initialize(TestI18nMissingProperty.class); 308 String text = TestI18nMissingProperty.testMessage1.text("test"); 309 assertThat(text.charAt(0), is('<')); 310 System.out.println("Text: " + text); 311 } 312 313 @Test 314 public void shouldHaveProblemIfPropertyMissing() { 315 I18n.initialize(TestI18nMissingProperty.class); 316 assertThat(TestI18nMissingProperty.testMessage1.hasProblem(), is(true)); 317 String problem = TestI18nMissingProperty.testMessage1.problem(); 318 assertThat(problem, notNullValue()); 319 System.out.println("Problem: " + problem); 320 } 321 322 @Test 323 public void shouldNotHaveLocalicationProblemIfPropertyMissing() { 324 I18n.initialize(TestI18nMissingProperty.class); 325 TestI18nMissingProperty.testMessage1.text("test"); 326 assertThat(I18n.getLocalizationProblems(TestI18nMissingProperty.class).isEmpty(), is(true)); 327 assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingProperty.class).isEmpty(), is(true)); 328 } 329 330 @Test 331 public void shouldHaveLocalicationProblemIfPropertyUnused() { 332 I18n.initialize(TestI18nUnusedProperty.class); 333 TestI18nUnusedProperty.testMessage.text("test"); 334 assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class).size(), is(1)); 335 assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).size(), is(1)); 336 assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).iterator().next(), is(Locale.getDefault())); 337 } 338 339 @Test 340 public void shouldHaveTextMatchingLocalizationFilePropertyValue() { 341 I18n.initialize(TestI18n.class); 342 assertThat(TestI18n.testMessage.text(), is("Test Message")); 343 } 344 345 @Test( expected = IllegalArgumentException.class ) 346 public void shouldFailIfTooFewArgumentsSuppliedToText() { 347 I18n.initialize(TestI18n.class); 348 try { 349 TestI18n.testMessage1.text(); 350 } catch (IllegalArgumentException err) { 351 System.err.println(err); 352 throw err; 353 } 354 } 355 356 @Test( expected = IllegalArgumentException.class ) 357 public void shouldFailIfTooManyArgumentsSuppliedToText() { 358 I18n.initialize(TestI18n.class); 359 try { 360 TestI18n.testMessage1.text("Test", "Message"); 361 } catch (IllegalArgumentException err) { 362 System.err.println(err); 363 throw err; 364 } 365 } 366 367 @Test 368 public void shouldContainArgumentsInRightOrderInText() { 369 I18n.initialize(TestI18n.class); 370 assertThat(TestI18n.testMessage2.text("Test", "Message"), is("Message Test")); 371 } 372 373 @Test 374 public void shouldAllowReuseOfArgumentsInText() { 375 I18n.initialize(TestI18n.class); 376 assertThat(TestI18n.testMessage3.text("Test", "Message"), is("Message Test Message")); 377 } 378 379 @Test 380 public void shouldContainLocaleSpecificText() { 381 I18n.initialize(TestI18n.class); 382 assertThat(TestI18n.testMessage.text(Locale.FRENCH), is("Message de Test")); 383 } 384 385 @Test 386 public void shouldContainTextForDefaultLocaleIfMissingLocalizationForSuppliedLocale() { 387 I18n.initialize(TestI18n.class); 388 assertThat(TestI18n.testMessage.text(Locale.CHINESE), is("Test Message")); 389 } 390 391 public static class TestI18n { 392 393 public static I18n testMessage; 394 public static I18n testMessage1; 395 public static I18n testMessage2; 396 public static I18n testMessage3; 397 public static Object nonI18n; 398 } 399 400 private static class TestI18nDuplicateProperty { 401 402 public static I18n testMessage; 403 } 404 405 public static final class TestI18nFinal { 406 407 public static I18n testMessage; 408 } 409 410 public static class TestI18nFinalField { 411 412 public static final I18n testMessage = null; 413 } 414 415 public static interface TestI18nInterface { 416 417 I18n testMessage = null; 418 } 419 420 private static class TestI18nMissingProperty { 421 422 @SuppressWarnings( "unused" ) 423 public static I18n testMessage; 424 public static I18n testMessage1; 425 } 426 427 public static class TestI18nNotPublicField { 428 429 static I18n testMessage; 430 } 431 432 public static class TestI18nNotStaticField { 433 434 public I18n testMessage; 435 } 436 437 private static class TestI18nPrivate { 438 439 public static I18n testMessage; 440 } 441 442 private static class TestI18nUnusedProperty { 443 444 public static I18n testMessage; 445 } 446 447 private static class TestI18nMissingLocalization { 448 449 public static I18n testMessage; 450 } 451}