001/* 002 * Copyright (c) 2012, 2013, Werner Keil, Credit Suisse (Anatole Tresch). Licensed under the Apache 003 * License, Version 2.0 (the "License"); you may not use this file except in compliance with the 004 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 005 * Unless required by applicable law or agreed to in writing, software distributed under the License 006 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 007 * or implied. See the License for the specific language governing permissions and limitations under 008 * the License. Contributors: Anatole Tresch - initial version. 009 */ 010package org.javamoney.tck.tests; 011 012import org.javamoney.tck.TCKTestSetup; 013import org.javamoney.tck.tests.internal.TestAmount; 014import org.javamoney.tck.tests.internal.TestCurrencyUnit; 015import org.javamoney.tck.tests.internal.TestMonetaryAmountBuilder; 016import org.jboss.test.audit.annotations.SpecAssertion; 017import org.jboss.test.audit.annotations.SpecVersion; 018import org.testng.AssertJUnit; 019import org.testng.annotations.Test; 020 021import javax.money.*; 022import java.math.BigDecimal; 023import java.math.RoundingMode; 024import java.util.Collection; 025import java.util.Currency; 026import java.util.Locale; 027import java.util.Set; 028 029import static org.junit.Assert.assertNotNull; 030 031 032/** 033 * Created by Anatole on 10.03.14. 034 */ 035@SpecVersion(spec = "JSR 354", version = "1.0.0") 036public class AccessingCurrenciesAmountsRoundingsTest { 037 038 // ****************** A. Accessing Currencies ******************* 039 040 /** 041 * Test if MonetaryCurrencies provides all ISO related entries, 042 * similar to the JDK. 043 */ 044 @Test(description = "4.2.7 Test if MonetaryCurrencies provides all ISO related entries similar to " + 045 "java.util.Currency.") 046 @SpecAssertion(section = "4.2.7", id = "427-A1") 047 public void testAllISOCurrenciesAvailable() { 048 for (Currency currency : Currency.getAvailableCurrencies()) { 049 AssertJUnit.assertTrue( 050 "Section 4.2.7: Currency not available [MonetaryCurrencies#isCurrencyAvailable(String)] for JDK " + 051 "currency code: " + 052 currency.getCurrencyCode(), 053 MonetaryCurrencies.isCurrencyAvailable(currency.getCurrencyCode())); 054 AssertJUnit.assertNotNull( 055 "Section 4.2.7: Currency null [MonetaryCurrencies#igetCurrency(String)] for JDK currency code: " + 056 currency.getCurrencyCode(), MonetaryCurrencies.getCurrency(currency.getCurrencyCode())); 057 } 058 } 059 060 /** 061 * Test if MonetaryCurrencies provides all Locale related 062 * entries, similar to the JDK (for all ISO countries). 063 */ 064 @Test(description = "4.2.7 Test if MonetaryCurrencies provides all locale related entries similar to " + 065 "java.util.Currency.") 066 @SpecAssertion(section = "4.2.7", id = "427-A2") 067 public void testAllLocaleCurrenciesAvailable() { 068 for (String country : Locale.getISOCountries()) { 069 Locale locale = new Locale("", country); 070 if (Currency.getInstance(locale) != null) { 071 AssertJUnit.assertTrue( 072 "Section 4.2.7: Currency not available [MonetaryCurrencies#isCurrencyAvailable(Locale)] for " + 073 "locale: " + 074 locale, MonetaryCurrencies.isCurrencyAvailable(locale)); 075 AssertJUnit 076 .assertNotNull("Currency null [MonetaryCurrencies#igetCurrency(Locale)] for locale: " + locale, 077 MonetaryCurrencies.getCurrencies(locale)); 078 Collection<CurrencyUnit> units = MonetaryCurrencies.getCurrencies(locale); 079 CurrencyUnit requiredCurrency = null; 080 for (CurrencyUnit cu : units) { 081 if (Currency.getInstance(locale).getCurrencyCode().equals(cu.getCurrencyCode())) { 082 requiredCurrency = cu; 083 break; 084 } 085 } 086 AssertJUnit.assertNotNull( 087 "Section 4.2.7: No Currency returned from [MonetaryCurrencies#getCurrencies(Locale)] for " + 088 "locale: " + 089 locale, requiredCurrency); 090 AssertJUnit.assertEquals( 091 "Section 4.2.7: Invalid Currency returned from [MonetaryCurrencies#getCurrencies(Locale)] for" + 092 " " + 093 "locale: " + 094 locale + 095 ", expected: " + Currency.getInstance(locale) + ", found: " + requiredCurrency, 096 MonetaryCurrencies.getCurrency(Currency.getInstance(locale).getCurrencyCode()), 097 requiredCurrency); 098 } 099 } 100 } 101 102 /** 103 * Test if MonetaryCurrencies provides correct instance with ISO 104 * codes. 105 */ 106 @Test(description = "4.2.7 Test if MonetaryCurrencies provides correct ISO related entries similar to " + 107 "java.util.Currency.") 108 @SpecAssertion(section = "4.2.7", id = "427-A3") 109 public void testCorrectISOCodes() { 110 for (Currency currency : Currency.getAvailableCurrencies()) { 111 CurrencyUnit unit = MonetaryCurrencies.getCurrency(currency.getCurrencyCode()); 112 AssertJUnit.assertEquals( 113 "Section 4.2.7: Invalid Currency code returned from [MonetaryCurrencies#igetCurrency(String)] for" + 114 " currency code:" + 115 " " + 116 currency.getCurrencyCode() + ", expected: " + 117 Currency.getInstance(currency.getCurrencyCode()).getCurrencyCode() + 118 ", found: " + unit.getCurrencyCode(), 119 Currency.getInstance(currency.getCurrencyCode()).getCurrencyCode(), unit.getCurrencyCode()); 120 AssertJUnit.assertEquals( 121 "Section 4.2.7: Invalid numeric code returned from [MonetaryCurrencies#igetCurrency(String)] for " + 122 "currency code: " + 123 currency.getCurrencyCode() + ", expected: " + 124 Currency.getInstance(currency.getCurrencyCode()).getNumericCode() + 125 ", found: " + unit.getNumericCode(), 126 Currency.getInstance(currency.getCurrencyCode()).getNumericCode(), unit.getNumericCode()); 127 AssertJUnit.assertEquals( 128 "Section 4.2.7: Invalid default fraction unit returned from [MonetaryCurrencies#igetCurrency" + 129 "(String)] for " + 130 "currency code: " + 131 currency.getCurrencyCode() + ", expected: " + 132 Currency.getInstance(currency.getCurrencyCode()).getDefaultFractionDigits() + 133 ", found: " + unit.getDefaultFractionDigits(), 134 Currency.getInstance(currency.getCurrencyCode()).getDefaultFractionDigits(), 135 unit.getDefaultFractionDigits()); 136 } 137 } 138 139 /** 140 * Test if MonetaryCurrencies provides correct instance with 141 * Locales. 142 */ 143 @Test(description = "4.2.7 Test if MonetaryCurrencies provides correct locale related entries similar to " + 144 "java.util.Currency.") 145 @SpecAssertion(section = "4.2.7", id = "427-A4") 146 public void testCorrectLocales() { 147 148 MonetaryCurrencies.getCurrencies(new Locale("", "AD")); 149 150 for (String country : Locale.getISOCountries()) { 151 Locale locale = new Locale("", country); 152 if (Currency.getInstance(locale) == null) { 153 continue; 154 } 155 Set<CurrencyUnit> units = MonetaryCurrencies.getCurrencies(locale); 156 AssertJUnit.assertNotNull( 157 "Section 4.2.7: Invalid Currencies (null) returned from [MonetaryCurrencies#igetCurrencies" + 158 "(Locale)] for" + 159 " locale: " + 160 locale, units); 161 AssertJUnit.assertFalse( 162 "Section 4.2.7: Empty Currencies returned from [MonetaryCurrencies#igetCurrencies(Locale)] for" + 163 " locale: " + 164 locale, units.isEmpty()); 165 CurrencyUnit requiredCurrency = null; 166 for (CurrencyUnit cu : units) { 167 if (Currency.getInstance(locale).getCurrencyCode().equals(cu.getCurrencyCode())) { 168 requiredCurrency = cu; 169 break; 170 } 171 } 172 AssertJUnit.assertNotNull("Section 4.2.7: Required Currency missing in result returned from " + 173 "[MonetaryCurrencies#igetCurrency(Locale)] for" + 174 " locale: " + 175 locale + ", expected: " + Currency.getInstance(locale).getCurrencyCode() + 176 ", found: " + units, requiredCurrency); 177 AssertJUnit.assertEquals( 178 "Section 4.2.7: Invalid numeric code returned from [MonetaryCurrencies#igetCurrency(Locale)] for " + 179 "locale: " + 180 locale + ", expected: " + Currency.getInstance(locale).getNumericCode() + 181 ", found: " + requiredCurrency.getNumericCode(), 182 Currency.getInstance(locale).getNumericCode(), requiredCurrency.getNumericCode()); 183 AssertJUnit.assertEquals( 184 "Section 4.2.7: Invalid default fraction unit returned from [MonetaryCurrencies#igetCurrency" + 185 "(Locale)] for " + 186 "locale: " + 187 locale + ", expected: " + Currency.getInstance(locale).getDefaultFractionDigits() + 188 ", found: " + requiredCurrency.getDefaultFractionDigits(), 189 Currency.getInstance(locale).getDefaultFractionDigits(), 190 requiredCurrency.getDefaultFractionDigits()); 191 } 192 } 193 194 /** 195 * Test for custom MonetaryCurrencies provided, based on the TCK 196 * TestProvider. 197 */ 198 @Test(description = "4.2.7 Test if MonetaryCurrencies provides customized locale identified currencies.") 199 @SpecAssertion(section = "4.2.7", id = "427-A5") 200 public void testCustomCurrencies() { 201 Locale testLocale = new Locale("lang", "count", "test"); 202 Set<CurrencyUnit> cus = MonetaryCurrencies.getCurrencies(testLocale); 203 AssertJUnit.assertNotNull("Section 4.2.7: TestCurrency not returned for locale: " + testLocale, cus); 204 AssertJUnit.assertFalse("Section 4.2.7: TestCurrency not returned for locale: " + testLocale, cus.isEmpty()); 205 AssertJUnit.assertEquals("Section 4.2.7: Unexpected CurrencyUnit class returned.", TestCurrencyUnit.class, 206 cus.iterator().next().getClass()); 207 CurrencyUnit cu = MonetaryCurrencies.getCurrency("FOOLS_test"); 208 AssertJUnit.assertNotNull("Section 4.2.7: TestCurrency not returned for currency code: FOOLS_test", cu); 209 AssertJUnit.assertEquals("Section 4.2.7: Unexpected CurrencyUnit class returned.", TestCurrencyUnit.class, 210 cu.getClass()); 211 } 212 213 // ********************************* B. Accessing Monetary Amount Factories *********************** 214 215 /** 216 * Ensure amount factories are accessible for all types 217 * available, 218 * providing also the 219 * some test implementations with the 220 * TCK. 221 */ 222 @Test(description = "4.2.7 Ensure amount classes to test are setup and registered/available in MonetaryAmounts.") 223 @SpecAssertion(section = "4.2.7", id = "427-B2") 224 public void testAmountTypesProvided() { 225 Collection<Class> amountClasses = TCKTestSetup.getTestConfiguration().getAmountClasses(); 226 AssertJUnit.assertNotNull(amountClasses); 227 AssertJUnit.assertFalse(amountClasses.isEmpty()); 228 Collection<Class<? extends MonetaryAmount>> providedClasses = MonetaryAmounts.getAmountTypes(); 229 for (Class amountType : amountClasses) { 230 AssertJUnit.assertTrue("Section 4.2.7: Amount class not registered: " + amountType.getName(), 231 providedClasses.contains(amountType)); 232 } 233 AssertJUnit.assertTrue("Section 4.2.7: TCK Amount class not registered: " + TestAmount.class, 234 providedClasses.contains(TestAmount.class)); 235 } 236 237 /** 238 * Ensure amount factories are accessible for all types 239 * available, 240 * providing also the 241 * some test implementations with the 242 * TCK, 243 * and that 244 * every factory accessed 245 * is a new instance. 246 */ 247 @Test(description = "4.2.7 Ensure amount factories are accessible for all types available in MonetaryAmounts.") 248 @SpecAssertion(section = "4.2.7", id = "427-B3") 249 public void testAmountTypesInstantiatable() { 250 Collection<Class> amountClasses = TCKTestSetup.getTestConfiguration().getAmountClasses(); 251 for (Class amountType : amountClasses) { 252 MonetaryAmountFactory<?> f = MonetaryAmounts.getAmountFactory(amountType); 253 AssertJUnit.assertNotNull("Section 4.2.7: MonetaryAmountFactory returned by MonetaryAmounts is null for " + 254 amountType.getName(), f); 255 MonetaryAmountFactory<?> f2 = MonetaryAmounts.getAmountFactory(amountType); 256 AssertJUnit.assertNotNull("Section 4.2.7: MonetaryAmountFactory returned by MonetaryAmounts is null for " + 257 amountType.getName(), f2); 258 AssertJUnit.assertNotSame("MonetaryAmountFactory instances are not distinct for " + amountType.getName(), f, 259 f2); 260 TestCurrencyUnit tc = new TestCurrencyUnit(); 261 MonetaryAmount m1 = f.setNumber(0L).setCurrency(tc).create(); 262 AssertJUnit.assertNotNull( 263 "Section 4.2.7: MonetaryAmountFactory creates null amounts for " + amountType.getName(), m1); 264 AssertJUnit.assertTrue( 265 "Section 4.2.7: MonetaryAmountFactory creates non zero amounts for " + amountType.getName(), 266 m1.isZero()); 267 AssertJUnit.assertEquals( 268 "Section 4.2.7: MonetaryAmountFactory creates non zero amounts for " + amountType.getName(), 0L, 269 m1.getNumber().longValue()); 270 AssertJUnit.assertTrue( 271 "Section 4.2.7: MonetaryAmountFactory creates non assignable amounts instances for " + 272 amountType.getName(), amountType.isAssignableFrom(m1.getClass())); 273 } 274 MonetaryAmountFactory<?> f = MonetaryAmounts.getAmountFactory(TestAmount.class); 275 AssertJUnit.assertNotNull("Section 4.2.7: MonetaryAmountFactory returned by MonetaryAmounts is null for " + 276 TestAmount.class.getName(), f); 277 AssertJUnit.assertEquals("MonetaryAmountFactory returned by MonetaryAmounts is obfuscated or proxied for " + 278 TestMonetaryAmountBuilder.class.getName(), TestMonetaryAmountBuilder.class, 279 f.getClass()); 280 } 281 282 /** 283 * Ensure correct query function implementations, providing also 284 * the some test implementations with the TCK. 285 */ 286 @Test(description = 287 "4.2.7 Ensure correct query function, MonetaryAmounts.getAmountFactories should return factory" + 288 "for explicit acquired amount types.") 289 @SpecAssertion(section = "4.2.7", id = "427-B4") 290 public void testAmountQueryType() { 291 MonetaryAmountFactoryQuery ctx = MonetaryAmountFactoryQueryBuilder.of().setTargetType(TestAmount.class).build(); 292 Collection<MonetaryAmountFactory<?>> factories = MonetaryAmounts.getAmountFactories(ctx); 293 AssertJUnit.assertNotNull("Section 4.2.7: Amount factory query should return explicitly queried factories", 294 factories); 295 boolean found = false; 296 for (MonetaryAmountFactory<?> f : factories) { 297 if (f.getAmountType().equals(TestAmount.class)) { 298 found = true; 299 break; 300 } 301 } 302 AssertJUnit.assertTrue("Section 4.2.7: Amount type query should return same explicitly queried factory", found); 303 ctx = MonetaryAmountFactoryQueryBuilder.of().build(); 304 MonetaryAmountFactory<?> factory = MonetaryAmounts.getAmountFactory(ctx); 305 AssertJUnit.assertNotNull("Section 4.2.7: Amount type must be provided", factory); 306 } 307 308 /** 309 * Ensure a default factory is returned. Test javamoney.config 310 * for configuring default value. 311 */ 312 @Test(description = "4.2.7 Ensure a default MonetaryAmountFactory is available.") 313 @SpecAssertion(section = "4.2.7", id = "427-B5") 314 public void testAmountDefaultType() { 315 AssertJUnit.assertNotNull("Section 4.2.7: No default MonetaryAmountFactory found.", 316 MonetaryAmounts.getDefaultAmountFactory()); 317 // TODO check default configuration... 318 } 319 320 // ********************************* C. Accessing Roundings ***************************** 321 322 /** 323 * Access roundings using all defined currencies, including TCK 324 * custom currencies. 325 */ 326 @Test(description = "4.2.7 Ensure MonetaryRoundings instances are available, for all registered currencies.") 327 @SpecAssertion(section = "4.2.7", id = "427-C1") 328 public void testAccessRoundingsForCustomCurrencies_Default() { 329 // Using default roundings... 330 TestCurrencyUnit cu = new TestCurrencyUnit("ASDF", 3); 331 MonetaryRounding r = MonetaryRoundings.getDefaultRounding(); 332 MonetaryAmount m = 333 new TestMonetaryAmountBuilder().setNumber(new BigDecimal("12.123456789101222232323")).setCurrency(cu) 334 .create(); 335 AssertJUnit.assertEquals( 336 "Section 4.2.7: expected ASDF 12.123 with default rounding from ASDF 12.123456789101222232323", 337 "ASDF 12.123", m.with(r).toString()); 338 // should not throw an error! 339 for (Currency currency : Currency.getAvailableCurrencies()) { 340 m = new TestMonetaryAmountBuilder().setNumber(new BigDecimal("12.123456789101222232323")) 341 .setCurrency(currency.getCurrencyCode()).create(); 342 if (currency.getDefaultFractionDigits() >= 0) { 343 MonetaryAmount rounded = m.with(r); // should not throw an error 344 AssertJUnit.assertEquals( 345 "Section 4.2.7: Returned amount class must be the same as the input class to the rounding " + 346 "operator.", TestAmount.class, rounded.getClass()); 347 AssertJUnit.assertEquals("Section 4.2.7: Rounding did change currency: " + rounded.getClass().getName(), 348 currency.getCurrencyCode(), rounded.getCurrency().getCurrencyCode()); 349 AssertJUnit.assertNotSame( 350 "Section 4.2.7: Rounding did not have any effect, should use scale==2 as default.", 351 m.getNumber().getScale(), rounded.getNumber().getScale()); 352 } 353 } 354 } 355 356 /** 357 * Access roundings using all defined currencies, including TCK 358 * custom currencies. 359 */ 360 @Test(description = "4.2.7 Ensure MonetaryRoundings instances are available, also for any custom currency " + 361 "(not registered).") 362 @SpecAssertion(section = "4.2.7", id = "427-C1") 363 public void testAccessRoundingsForCustomCurrencies_Explicit() { 364 // Using default roundings... 365 TestCurrencyUnit cu = new TestCurrencyUnit("ASDF", 3); 366 MonetaryOperator r = MonetaryRoundings.getRounding(cu); 367 MonetaryAmount m = 368 new TestMonetaryAmountBuilder().setNumber(new BigDecimal("12.123456789101222232323")).setCurrency(cu) 369 .create(); 370 AssertJUnit.assertEquals("Section 4.2.7: Expected ASDF 12.123 for custom rounding 12.123456789101222232323.", 371 "ASDF 12.123", m.with(r).toString()); 372 // should not throw an error! 373 for (Currency currency : Currency.getAvailableCurrencies()) { 374 if (currency.getDefaultFractionDigits() >= 0) { 375 r = MonetaryRoundings.getRounding(cu); 376 m = m.with(r); // should not throw an error 377 AssertJUnit.assertEquals( 378 "Section 4.2.7: Expected ASDF 12.123 for rounding for Currency" + cu.getCurrencyCode(), 379 "ASDF 12.123", m.with(r).toString()); 380 } else { 381 try { 382 r = MonetaryRoundings.getRounding(cu); 383 AssertJUnit.assertNotNull(r); 384 } catch (MonetaryException e) { 385 // OK 386 } 387 } 388 } 389 } 390 391 /** 392 * Access roundings using all defined currencies, including TCK 393 * custom currencies. 394 */ 395 @Test(expectedExceptions = NullPointerException.class, 396 description = "4.2.7: Expected NullPointerException accessing a rounding with " + 397 "'MonetaryRoundings.getRounding(null)'.") 398 @SpecAssertion(section = "4.2.7", id = "427-C1") 399 public void testAccessRoundingsForCustomCurrencies_Explicit_Null() { 400 MonetaryRoundings.getRounding((CurrencyUnit) null); 401 } 402 403 404 /** 405 * Access roundings using a MonetaryContext. Use different 406 * MathContext/RoundingMode, as an attribute, when running 407 * on the JDK. 408 */ 409 @Test(description = "4.2.7 Ensure correct MonetaryRounding returned for a mathematical RoundingQuery.") 410 @SpecAssertion(section = "4.2.7", id = "427-C2") 411 public void testAccessRoundingsWithRoundingContext() { 412 RoundingQuery ctx = RoundingQueryBuilder.of().setScale(1).set(RoundingMode.UP).build(); 413 MonetaryOperator r = MonetaryRoundings.getRounding(ctx); 414 AssertJUnit.assertNotNull("Section 4.2.7: No rounding provided for RoundingQuery: " + ctx, r); 415 MonetaryAmount m = 416 new TestMonetaryAmountBuilder().setNumber(new BigDecimal("12.123456789101222232323")).setCurrency("CHF") 417 .create(); 418 AssertJUnit.assertEquals("Section 4.2.7: Invalid rounding provided for RoundingQuery: " + ctx, "CHF 12.2", 419 m.with(r).toString()); 420 } 421 422 /** 423 * Access roundings using a RoundingContext, that is null. 424 */ 425 @Test(expectedExceptions = NullPointerException.class, 426 description = "4.2.7: Ensure NullPointerException is thrown for " + 427 "'MonetaryRoundings.getRounding((RoundingContext) null)'.") 428 @SpecAssertion(section = "4.2.7", id = "427-C2") 429 public void testAccessRoundingsWithMonetaryContext_Null() { 430 MonetaryRoundings.getRounding(null); 431 } 432 433 /** 434 * Access custom roundings and ensure TCK custom roundings are 435 * registered. 436 */ 437 @Test(description = "4.2.7 Access named roundings and ensure TCK named roundings are " + "registered.") 438 @SpecAssertion(section = "4.2.7", id = "427-C3") 439 public void testAccessCustomRoundings() { 440 Set<String> ids = MonetaryRoundings.getRoundingNames(); 441 AssertJUnit.assertNotNull("Section 4.2.7: Custom Rounding key are null", ids); 442 AssertJUnit 443 .assertTrue("Section 4.2.7: At least NOSCALE custom rounding must be present", ids.contains("NOSCALE")); 444 } 445 446 /** 447 * Test TCK custom roundings. 448 */ 449 @Test(description = "4.2.7 Access custom roundings and ensure correct functionality.") 450 @SpecAssertion(section = "4.2.7", id = "427-C4") 451 public void testCustomRoundings() { 452 MonetaryOperator r = MonetaryRoundings.getRounding("NOSCALE"); 453 AssertJUnit.assertNotNull(r); 454 MonetaryAmount m = 455 new TestMonetaryAmountBuilder().setNumber(new BigDecimal("12.123456789101222232323")).setCurrency("CHF") 456 .create(); 457 AssertJUnit.assertEquals("Section 4.2.7: Expected CHF 12 for NOSCALE operator on " + m, "CHF 12", 458 m.with(r).toString()); 459 } 460 461 /** 462 * Test TCK custom roundings. 463 */ 464 @Test(expectedExceptions = NullPointerException.class, 465 description = "4.2.7 Ensure NullPointerException is thrown for MonetaryRoundings.getRounding((String) null).") 466 @SpecAssertion(section = "4.2.7", id = "427-C4") 467 public void testCustomRoundings_Null() { 468 MonetaryRoundings.getRounding((String) null); 469 } 470 471 /** 472 * Test TCK custom roundings. 473 */ 474 @Test(expectedExceptions = MonetaryException.class, 475 description = "4.2.7 Ensure MonetaryException is thrown for " + "accessing invalid named rounding.") 476 @SpecAssertion(section = "4.2.7", id = "427-C4") 477 public void testCustomRoundings_Foo() { 478 assertNotNull("Section 4.2.7: Expected custom rounding with name 'foo'.", MonetaryRoundings.getRounding("foo")); 479 } 480 481}