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.TestUtils; 014import org.javamoney.tck.tests.internal.TestAmount; 015import org.jboss.test.audit.annotations.SpecAssertion; 016import org.jboss.test.audit.annotations.SpecVersion; 017import org.mutabilitydetector.unittesting.MutabilityAssertionError; 018import org.testng.AssertJUnit; 019import org.testng.annotations.Test; 020 021import javax.money.*; 022import java.math.BigDecimal; 023import java.math.RoundingMode; 024import java.util.ArrayList; 025import java.util.Currency; 026import java.util.List; 027 028import static javax.money.MonetaryAmounts.getAmountFactory; 029 030@SpecVersion(spec = "JSR 354", version = "1.0.0") 031public class ModellingMonetaryAmountsTest { 032 033 private final static String DEFAULT_CURRENCY = "CHF"; 034 035 private final static String ADDITIONAL_CURRENCY = "USD"; 036 037 /** 038 * Ensure at least one javax.money.MonetaryAmount implementation is registered, 039 * by calling MonetaryAmounts.getAmountTypes(); 040 */ 041 @SpecAssertion(section = "4.2.2", id = "422-0") 042 @Test(description = "4.2.2 Ensure MonetaryAmounts.getAmountTypes() is not null and not empty.") 043 public void testEnsureMonetaryAmount() { 044 AssertJUnit.assertNotNull("Section 4.2.2: MonetaryAmounts.getAmountTypes() must never return null.", 045 MonetaryAmounts.getAmountTypes()); 046 AssertJUnit.assertTrue( 047 "Section 4.2.2: At least one type must be registered with MonetaryAmounts (see getAmountTypes()).", 048 MonetaryAmounts.getAmountTypes().size() > 0); 049 } 050 051 /** 052 * For each MonetaryAmount implementation: Ensure getCurrencyCode 053 * returns correct results. 054 */ 055 @SpecAssertion(section = "4.2.2", id = "422-A1") 056 @Test(description = "4.2.2 Ensure amount can be created with all default currencies.") 057 public void testCurrencyCode() { 058 for (Class type : MonetaryAmounts.getAmountTypes()) { 059 for (Currency jdkCur : Currency.getAvailableCurrencies()) { 060 MonetaryAmount amount = 061 MonetaryAmounts.getDefaultAmountFactory().setCurrency(jdkCur.getCurrencyCode()).setNumber(10.15) 062 .create(); 063 AssertJUnit.assertNotNull( 064 "Section 4.2.2: Amount factory returned null for new amount type: " + type.getName(), amount); 065 AssertJUnit.assertNotNull( 066 "Section 4.2.2: Amount factory returned new amount with null currency, type: " + type.getName(), 067 amount.getCurrency()); 068 AssertJUnit.assertEquals( 069 "Section 4.2.2: Amount factory returned new amount with invalid currency, type: " + 070 type.getName(), jdkCur.getCurrencyCode(), amount.getCurrency().getCurrencyCode()); 071 } 072 } 073 } 074 075 /** 076 * For each MonetaryAmount implementation: Ensure getNumber() 077 * returns correct results. 078 */ 079 @SpecAssertion(section = "4.2.2", id = "422-A2") 080 @Test(description = "4.2.2 Ensure amounts created return correct getNumber().") 081 public void testGetNumber() { 082 for (Class type : MonetaryAmounts.getAmountTypes()) { 083 if (type.equals(TestAmount.class)) { 084 continue; 085 } 086 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 087 f.setCurrency("CHF"); 088 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(100).create(), 089 f.setNumber(new BigDecimal("23123213.435")).create(), 090 f.setNumber(new BigDecimal("-23123213.435")).create(), f.setNumber(-23123213).create(), 091 f.setNumber(0).create()}; 092 BigDecimal[] numbers = new BigDecimal[]{new BigDecimal("100"), new BigDecimal("23123213.435"), 093 new BigDecimal("-23123213.435"), new BigDecimal("-23123213"), BigDecimal.ZERO}; 094 int[] intNums = new int[]{100, 23123213, -23123213, -23123213, 0}; 095 long[] longNums = new long[]{100, 23123213, -23123213, -23123213, 0}; 096 double[] doubleNums = new double[]{100, 23123213.435, -23123213.435, -23123213, 0}; 097 float[] floatNums = new float[]{100f, 23123213.435f, -23123213.435f, -23123213, 0f}; 098 099 for (int i = 0; i < moneys.length; i++) { 100 NumberValue nv = moneys[i].getNumber(); 101 AssertJUnit.assertNotNull("Section 4.2.2: Amount returned returns null for getNumber(), type: " + 102 moneys[i].getClass().getName(), nv); 103 AssertJUnit.assertEquals( 104 "Section 4.2.2: getNumber().numberValue(BigDecimal.class) incorrect for " + type.getName(), 105 numbers[i].stripTrailingZeros(), nv.numberValue(BigDecimal.class).stripTrailingZeros()); 106 AssertJUnit.assertEquals("Section 4.2.2: getNumber().intValue() incorrect for " + type.getName(), 107 intNums[i], nv.intValue()); 108 AssertJUnit.assertEquals("Section 4.2.2: getNumber().longValue() incorrect for " + type.getName(), 109 longNums[i], nv.longValue()); 110 AssertJUnit.assertEquals("Section 4.2.2: getNumber().doubleValue() incorrect for " + type.getName(), 111 doubleNums[i], nv.doubleValue(), 0.0d); 112 AssertJUnit.assertEquals("Section 4.2.2: getNumber().floatValue() incorrect for " + type.getName(), 113 floatNums[i], nv.floatValue(), 0.0d); 114 } 115 } 116 } 117 118 /** 119 * For each MonetaryAmount implementation: Ensure 120 * getContext() returns correct results. 121 */ 122 @SpecAssertion(section = "4.2.2", id = "422-A3") 123 @Test(description = "4.2.2 Ensure amounts created return correct getContext().") 124 public void testGetMonetaryContext() { 125 for (Class type : MonetaryAmounts.getAmountTypes()) { 126 if (type.equals(TestAmount.class)) { 127 continue; 128 } 129 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 130 f.setCurrency("CHF"); 131 MonetaryContext defCtx = f.getDefaultMonetaryContext(); 132 MonetaryContext maxCtx = f.getMaximalMonetaryContext(); 133 MonetaryContext mc = f.setNumber(1).create().getContext(); 134 AssertJUnit.assertEquals("Section 4.2.2: Invalid MonetaryContext(amountType) for " + type.getName(), 135 mc.getAmountType(), type); 136 if (maxCtx.getPrecision() > 0) { 137 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(precision) for " + type.getName(), 138 mc.getPrecision() <= maxCtx.getPrecision()); 139 } 140 if (maxCtx.getMaxScale() > 0) { 141 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(maxScale) for " + type.getName(), 142 mc.getMaxScale() <= maxCtx.getMaxScale()); 143 } 144 AssertJUnit.assertEquals("Section 4.2.2: Invalid MonetaryContext(amountType) for " + type.getName(), 145 f.setNumber(0.34746d).create().getContext().getAmountType(), type); 146 mc = f.setNumber(0).create().getContext(); 147 AssertJUnit.assertEquals("Section 4.2.2: Invalid MonetaryContext(amountType) for " + type.getName(), 148 mc.getAmountType(), type); 149 if (maxCtx.getPrecision() > 0) { 150 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(precision) for " + type.getName(), 151 mc.getPrecision() <= maxCtx.getPrecision()); 152 } 153 if (maxCtx.getMaxScale() > 0) { 154 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(maxScale) for " + type.getName(), 155 mc.getMaxScale() <= maxCtx.getMaxScale()); 156 } 157 AssertJUnit.assertEquals("Section 4.2.2: Invalid MonetaryContext(amountType) for " + type.getName(), 158 f.setNumber(100034L).create().getContext().getAmountType(), type); 159 mc = f.setNumber(0).create().getContext(); 160 AssertJUnit.assertEquals("Section 4.2.2: Invalid MonetaryContext(amountType) for " + type.getName(), 161 mc.getAmountType(), type); 162 if (maxCtx.getPrecision() > 0) { 163 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(precision) for " + type.getName(), 164 mc.getPrecision() <= maxCtx.getPrecision()); 165 } 166 if (maxCtx.getMaxScale() > 0) { 167 AssertJUnit.assertTrue("Section 4.2.2: Invalid MonetaryContext(maxScale) for " + type.getName(), 168 mc.getMaxScale() <= maxCtx.getMaxScale()); 169 } 170 } 171 } 172 173 /** 174 * For each MonetaryAmount implementation: Ensure isNegative() 175 * returns correct results. 176 */ 177 @SpecAssertion(section = "4.2.2", id = "422-A4") 178 @Test(description = "4.2.2 For each amount class, test isNegative().") 179 public void testIsNegative() { 180 for (Class type : MonetaryAmounts.getAmountTypes()) { 181 if (type.equals(TestAmount.class)) { 182 continue; 183 } 184 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 185 f.setCurrency("CHF"); 186 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(0).create(), f.setNumber(0.0).create(), 187 f.setNumber(BigDecimal.ZERO).create(), f.setNumber(new BigDecimal("0.00000000000000000")).create(), 188 f.setNumber(100).create(), f.setNumber(34242344).create(), f.setNumber(23123213.435).create()}; 189 for (MonetaryAmount m : moneys) { 190 AssertJUnit.assertFalse("Section 4.2.2: Invalid isNegative (expected false) for " + type.getName(), 191 m.isNegative()); 192 } 193 moneys = new MonetaryAmount[]{f.setNumber(-100).create(), f.setNumber(-34242344).create(), 194 f.setNumber(-23123213.435).create()}; 195 for (MonetaryAmount m : moneys) { 196 AssertJUnit.assertTrue("Section 4.2.2: Invalid isNegative (expected true) for " + type.getName(), 197 m.isNegative()); 198 } 199 } 200 } 201 202 /** 203 * For each MonetaryAmount implementation: Ensure isPositive() 204 * returns correct results. 205 */ 206 @SpecAssertion(section = "4.2.2", id = "422-A5") 207 @Test(description = "4.2.2 For each amount class, test isPositive().") 208 public void testIsPositive() { 209 for (Class type : MonetaryAmounts.getAmountTypes()) { 210 if (type.equals(TestAmount.class)) { 211 continue; 212 } 213 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 214 f.setCurrency("CHF"); 215 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(100).create(), f.setNumber(34242344).create(), 216 f.setNumber(23123213.435).create()}; 217 for (MonetaryAmount m : moneys) { 218 AssertJUnit.assertTrue("Section 4.2.2: Invalid isPositive (expected true) for " + type.getName(), 219 m.isPositive()); 220 } 221 moneys = new MonetaryAmount[]{f.setNumber(0).create(), f.setNumber(0.0).create(), 222 f.setNumber(BigDecimal.ZERO).create(), f.setNumber(new BigDecimal("0.00000000000000000")).create(), 223 f.setNumber(-100).create(), f.setNumber(-34242344).create(), f.setNumber(-23123213.435).create()}; 224 for (MonetaryAmount m : moneys) { 225 AssertJUnit.assertFalse("Section 4.2.2: Invalid isPositive (expected false) for " + type.getName(), 226 m.isPositive()); 227 } 228 } 229 } 230 231 232 /** 233 * For each MonetaryAmount implementation: Ensure isZero() 234 * returns correct results. 235 */ 236 @SpecAssertion(section = "4.2.2", id = "422-A6") 237 @Test(description = "4.2.2 For each amount class, test isZero().") 238 public void testIsZero() { 239 for (Class type : MonetaryAmounts.getAmountTypes()) { 240 if (type.equals(TestAmount.class)) { 241 continue; 242 } 243 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 244 f.setCurrency("CHF"); 245 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(100).create(), f.setNumber(34242344).create(), 246 f.setNumber(23123213.435).create(), f.setNumber(-100).create(), 247 f.setNumber(-723527.36532).create()}; 248 for (MonetaryAmount m : moneys) { 249 AssertJUnit.assertFalse("Section 4.2.2: Invalid isZero (expected false) for " + type.getName(), 250 m.isZero()); 251 } 252 moneys = new MonetaryAmount[]{f.setNumber(0).create(), f.setNumber(0.0).create(), 253 f.setNumber(BigDecimal.ZERO).create(), f.setNumber(new BigDecimal("0.00000000000000000")).create()}; 254 for (MonetaryAmount m : moneys) { 255 AssertJUnit 256 .assertTrue("Section 4.2.2: Invalid isZero (expected true) for " + type.getName(), m.isZero()); 257 } 258 } 259 } 260 261 /** 262 * For each MonetaryAmount implementation: Ensure isZero() 263 * returns correct results (-0, +0 == 0). 264 */ 265 @SpecAssertion(section = "4.2.2", id = "422-A6") 266 @Test(description = "4.2.2 For each amount class, test isZero(), advanced.") 267 public void testIsZeroAdvanced() { 268 for (Class type : MonetaryAmounts.getAmountTypes()) { 269 if (type.equals(TestAmount.class)) { 270 continue; 271 } 272 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 273 f.setCurrency("CHF"); 274 MonetaryAmount[] moneys = 275 new MonetaryAmount[]{f.setNumber(-0).create(), f.setNumber(0).create(), f.setNumber(-0.0f).create(), 276 f.setNumber(0.0f).create(), f.setNumber(-0.0d).create(), f.setNumber(0.0d).create()}; 277 for (MonetaryAmount m : moneys) { 278 AssertJUnit 279 .assertTrue("Section 4.2.2: Invalid isZero (expected true) for " + type.getName(), m.isZero()); 280 } 281 } 282 } 283 284 /** 285 * For each MonetaryAmount implementation: signum() function is 286 * implemented correctly. 287 */ 288 @SpecAssertion(section = "4.2.2", id = "422-A7") 289 @Test(description = "4.2.2 For each amount class, test signum().") 290 public void testSignum() { 291 for (Class type : MonetaryAmounts.getAmountTypes()) { 292 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 293 f.setCurrency("CHF"); 294 MonetaryAmount m = f.setNumber(100).create(); 295 AssertJUnit.assertEquals("Section 4.2.2: Invalid signum of 100 for " + type.getName(), 1, m.signum()); 296 m = f.setNumber(-100).create(); 297 AssertJUnit.assertEquals("Section 4.2.2: signum of -100 for " + type.getName(), -1, m.signum()); 298 m = f.setNumber(100.3435).create(); 299 AssertJUnit.assertEquals("Section 4.2.2: signum of 100.3435 for " + type.getName(), 1, m.signum()); 300 m = f.setNumber(-100.3435).create(); 301 AssertJUnit.assertEquals("Section 4.2.2: signum of -100.3435 for " + type.getName(), -1, m.signum()); 302 m = f.setNumber(0).create(); 303 AssertJUnit.assertEquals("Section 4.2.2: signum of 0 for " + type.getName(), 0, m.signum()); 304 m = f.setNumber(-0).create(); 305 AssertJUnit.assertEquals("Section 4.2.2: signum of - for " + type.getName(), 0, m.signum()); 306 } 307 } 308 309 /** 310 * For each MonetaryAmount implementation: Ensure isNegativeOrZero() 311 * returns correct results. 312 */ 313 @SpecAssertion(section = "4.2.2", id = "422-A8") 314 @Test(description = "4.2.2 For each amount class, test isNegativeOrZero().") 315 public void testIsNegativeOrZero() { 316 for (Class type : MonetaryAmounts.getAmountTypes()) { 317 if (type.equals(TestAmount.class)) { 318 continue; 319 } 320 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 321 f.setCurrency("CHF"); 322 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(100).create(), f.setNumber(34242344).create(), 323 f.setNumber(23123213.435).create()}; 324 for (MonetaryAmount m : moneys) { 325 AssertJUnit.assertFalse("Section 4.2.2: Invalid negativeOrZero (expected false) for " + type.getName(), 326 m.isNegativeOrZero()); 327 } 328 moneys = new MonetaryAmount[]{f.setNumber(0).create(), f.setNumber(0.0).create(), 329 f.setNumber(BigDecimal.ZERO).create(), f.setNumber(new BigDecimal("0.0000")).create(), 330 f.setNumber(-100).create(), f.setNumber(-34242344).create(), f.setNumber(-23123213.435).create()}; 331 for (MonetaryAmount m : moneys) { 332 AssertJUnit.assertTrue("Section 4.2.2: Invalid negativeOrZero (expected true) for " + type.getName(), 333 m.isNegativeOrZero()); 334 } 335 } 336 } 337 338 /** 339 * For each MonetaryAmount implementation: Ensure isPositiveOrZero() 340 * returns correct results. 341 */ 342 @SpecAssertion(section = "4.2.2", id = "422-A9") 343 @Test(description = "4.2.2 For each amount class, test isPositiveOrZero().") 344 public void testIsPositiveOrZero() { 345 for (Class type : MonetaryAmounts.getAmountTypes()) { 346 if (type.equals(TestAmount.class)) { 347 continue; 348 } 349 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 350 f.setCurrency("CHF"); 351 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(0).create(), f.setNumber(0.0).create(), 352 f.setNumber(BigDecimal.ZERO).create(), f.setNumber(new BigDecimal("0.00000000000000000")).create(), 353 f.setNumber(100).create(), f.setNumber(34242344).create(), f.setNumber(23123213.435).create()}; 354 for (MonetaryAmount m : moneys) { 355 AssertJUnit.assertTrue("Section 4.2.2: Invalid positiveOrZero (expected true): for " + type.getName(), 356 m.isPositiveOrZero()); 357 } 358 moneys = new MonetaryAmount[]{f.setNumber(-100).create(), f.setNumber(-34242344).create(), 359 f.setNumber(-23123213.435).create()}; 360 for (MonetaryAmount m : moneys) { 361 AssertJUnit 362 .assertFalse("Section 4.2.2: Invalid positiveOrZero (expected false) for " + type.getName() + m, 363 m.isPositiveOrZero()); 364 } 365 } 366 } 367 368 369 // ********************* B. Prototyping Support ***************************** 370 371 /** 372 * Ensure getFactory returns a MonetaryAmountFactory and that 373 * instances created are of the same type. 374 */ 375 @SpecAssertion(section = "4.2.2", id = "422-B1") 376 @Test(description = "4.2.2 For each amount class, access factory and of amounts.") 377 public void testMonetaryAmountFactories() { 378 for (Class type : MonetaryAmounts.getAmountTypes()) { 379 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 380 AssertJUnit.assertNotNull(f); 381 MonetaryAmount m = f.setCurrency("CHF").setNumber(10).create(); 382 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 383 m.getClass(), type); 384 m = f.setCurrency("CHF").setNumber(-10).create(); 385 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 386 m.getClass(), type); 387 m = f.setCurrency("CHF").setNumber(10.3).create(); 388 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 389 m.getClass(), type); 390 m = f.setCurrency("CHF").setNumber(-10.3).create(); 391 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 392 m.getClass(), type); 393 m = f.setCurrency("CHF").setNumber(0.0).create(); 394 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 395 m.getClass(), type); 396 m = f.setCurrency("CHF").setNumber(-0.0).create(); 397 AssertJUnit.assertEquals("Section 4.2.2: Invalid class for created amount, expected: " + type.getName(), 398 m.getClass(), type); 399 } 400 } 401 402 /** 403 * Call getFactory(), of a new MonetaryAmount instance, with 404 * same input. The instances must 405 * be equal (or even be identical!). 406 */ 407 @SpecAssertion(section = "4.2.2", id = "422-B2") 408 @Test(description = "4.2.2 For each amount class, access factory and of amounts, ensure amounts are equal if they" + 409 "should.") 410 public void testMonetaryAmountFactories_InstancesMustBeEqual() { 411 for (Class type : MonetaryAmounts.getAmountTypes()) { 412 if (type.equals(TestAmount.class)) { 413 continue; 414 } 415 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 416 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10).create(); 417 f = getAmountFactory(type); 418 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(10).create(); 419 AssertJUnit.assertEquals("Section 4.2.2: Expected equal instances for " + type.getName(), m1, m2); 420 } 421 422 for (Class type : MonetaryAmounts.getAmountTypes()) { 423 if (type.equals(TestAmount.class)) { 424 continue; 425 } 426 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 427 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10.5d).create(); 428 f = getAmountFactory(type); 429 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(10.5d).create(); 430 AssertJUnit 431 .assertEquals("Section 4.2.2: Expected equal types created by same factory for " + type.getName(), 432 m1, m2); 433 } 434 435 for (Class type : MonetaryAmounts.getAmountTypes()) { 436 if (type.equals(TestAmount.class)) { 437 continue; 438 } 439 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 440 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(new BigDecimal("10.52")).create(); 441 f = getAmountFactory(type); 442 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(new BigDecimal("10.52")).create(); 443 AssertJUnit 444 .assertEquals("Section 4.2.2: Expected equal types created by same factory for " + type.getName(), 445 m1, m2); 446 } 447 } 448 449 /** 450 * Call getFactory(), of a new MonetaryAmount instance with a 451 * new number 452 * value. The instances must 453 * be non equal and have the 454 * according 455 * numeric value. 456 */ 457 @SpecAssertion(section = "4.2.2", id = "422-B3") 458 @Test(description = "4.2.2 For each amount class, check new amounts are not equal.") 459 public void testMonetaryAmountFactories_InstantesMustBeNotEqual() { 460 for (Class type : MonetaryAmounts.getAmountTypes()) { 461 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 462 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10).create(); 463 f = getAmountFactory(type); 464 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(11).create(); 465 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 466 } 467 468 for (Class type : MonetaryAmounts.getAmountTypes()) { 469 MonetaryAmountFactory f = getAmountFactory(type); 470 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10.5d).create(); 471 f = getAmountFactory(type); 472 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(10.4d).create(); 473 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 474 } 475 476 for (Class type : MonetaryAmounts.getAmountTypes()) { 477 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 478 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(new BigDecimal("10.52")).create(); 479 f = getAmountFactory(type); 480 MonetaryAmount m2 = f.setCurrency("CHF").setNumber(new BigDecimal("10.11")).create(); 481 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 482 } 483 } 484 485 /** 486 * Call getFactory(),of a new MonetaryAmount instance 487 * with a new currency value.The instances must 488 * be non equal and have the according currency value .Do this by passing a literal code 489 * and by passing a CurrencyUnit. 490 */ 491 @SpecAssertion(section = "4.2.2", id = "422-B4") 492 @Test(description = "4.2.2 For each amount class, check multiple instances are not equal.") 493 public void testMonetaryAmountFactories_CreateWithCurrencies() { 494 for (Class type : MonetaryAmounts.getAmountTypes()) { 495 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 496 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10).create(); 497 f = getAmountFactory(type); 498 MonetaryAmount m2 = f.setCurrency("USD").setNumber(10).create(); 499 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 500 } 501 502 for (Class type : MonetaryAmounts.getAmountTypes()) { 503 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 504 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(10.5d).create(); 505 f = getAmountFactory(type); 506 MonetaryAmount m2 = f.setCurrency("USD").setNumber(10.5d).create(); 507 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 508 } 509 510 for (Class type : MonetaryAmounts.getAmountTypes()) { 511 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 512 MonetaryAmount m1 = f.setCurrency("CHF").setNumber(new BigDecimal("10.52")).create(); 513 f = getAmountFactory(type); 514 MonetaryAmount m2 = f.setCurrency("USD").setNumber(new BigDecimal("10.52")).create(); 515 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 516 } 517 } 518 519 /** 520 * Call getFactory(),of a new MonetaryAmount instance 521 * with a new monetary context(if possible-check the max context). The 522 * instances must be non equal and have the same currency and number value. 523 */ 524 @SpecAssertion(section = "4.2.2", id = "422-B5") 525 @Test(description = "4.2.2 For each amount class, check new amounts with explcit MonetaryContext.") 526 public void testMonetaryAmountFactories_CreateWithMonetaryContext() { 527 for (Class type : MonetaryAmounts.getAmountTypes()) { 528 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 529 MonetaryContext mc1 = f.getDefaultMonetaryContext(); 530 MonetaryContext mc2 = f.getMaximalMonetaryContext(); 531 MonetaryAmount m1; 532 MonetaryAmount m2; 533 if (mc1.equals(mc2)) { 534 // In this cases both amount must be equals 535 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10).create(); 536 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10).create(); 537 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 538 } else { 539 // In this cases both amount must be non equals 540 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10).create(); 541 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10).create(); 542 AssertJUnit.assertNotSame("Section 4.2.2: Expected non equal instances for " + type.getName(), m1, m2); 543 } 544 AssertJUnit.assertTrue("Section 4.2.2: Expected equality for " + type.getName(), m1.equals(m1)); 545 AssertJUnit.assertTrue("Section 4.2.2: Expected equality for " + type.getName(), m2.equals(m2)); 546 } 547 } 548 549 /** 550 * Call getFactory(),of a new MonetaryAmount instance with a new monetary context, a 551 * new number and a new currency. The instances must be non equal. 552 */ 553 @SpecAssertion(section = "4.2.2", id = "422-B6") 554 @Test(description = "4.2.2 For each amount class, check new amounts are not equal for different currencies and " + 555 "contexts.") 556 public void testMonetaryAmountFactories_CreateWithMonetaryContextNumberAndCurrency() { 557 for (Class type : MonetaryAmounts.getAmountTypes()) { 558 if (type.equals(TestAmount.class)) { 559 continue; 560 } 561 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 562 MonetaryContext mc1 = f.getDefaultMonetaryContext(); 563 MonetaryContext mc2 = f.getMaximalMonetaryContext(); 564 MonetaryAmount m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10).create(); 565 MonetaryAmount m2 = f.setCurrency("USD").setContext(mc2).setNumber(11).create(); 566 AssertJUnit.assertNotSame("Section 4.2.2: Expected not same for " + type.getName(), m1, m2); 567 AssertJUnit.assertTrue("Section 4.2.2: Expected isEqualTo==true for " + type.getName(), m1.isEqualTo(m1)); 568 AssertJUnit.assertTrue("Section 4.2.2: Expected isEqualTo==true for " + type.getName(), m2.isEqualTo(m2)); 569 AssertJUnit.assertTrue("Section 4.2.2: Expected equality for " + type.getName(), m1.equals(m1)); 570 AssertJUnit.assertTrue("Section 4.2.2: Expected equality for " + type.getName(), m2.equals(m2)); 571 } 572 } 573 574 // ***************************** C.Comparison Methods ********************************* 575 576 /** 577 * Test isGreaterThan() is implemented correctly for each amount type regardless of trailing zeroes. 578 */ 579 @SpecAssertion(section = "4.2.2", id = "422-C1") 580 @Test(description = "4.2.2 For each amount class, check isGreaterThan().") 581 public void testMonetaryAmount_isGreaterThan() { 582 for (Class type : MonetaryAmounts.getAmountTypes()) { 583 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 584 f.setCurrency("CHF"); 585 AssertJUnit.assertFalse("Section 4.2.2: isGreaterThan failed for " + type.getName(), 586 f.setNumber(BigDecimal.valueOf(0d)).create() 587 .isGreaterThan(f.setNumber(BigDecimal.valueOf(0)).create())); 588 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThan failed for " + type.getName(), 589 f.setNumber(BigDecimal.valueOf(0.00001d)).create() 590 .isGreaterThan(f.setNumber(BigDecimal.valueOf(0d)).create())); 591 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThan failed for " + type.getName(), 592 f.setNumber(15).create().isGreaterThan(f.setNumber(10).create())); 593 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThan failed for " + type.getName(), 594 f.setNumber(15.546).create().isGreaterThan(f.setNumber(10.34).create())); 595 AssertJUnit.assertFalse("Section 4.2.2: isGreaterThan failed for " + type.getName(), 596 f.setNumber(5).create().isGreaterThan(f.setNumber(10).create())); 597 AssertJUnit.assertFalse("Section 4.2.2: isGreaterThan failed for " + type.getName(), 598 f.setNumber(5.546).create().isGreaterThan(f.setNumber(10.34).create())); 599 } 600 } 601 602 /** 603 * Test isGreaterThanOrEquals() is implemented correctly for each amount type regardless of trailing 604 * zeroes. 605 */ 606 @SpecAssertion(section = "4.2.2", id = "422-C2") 607 @Test(description = "4.2.2 For each amount class, check isGreaterThanOrEquals().") 608 public void testMonetaryAmount_isGreaterThanOrEquals() { 609 for (Class type : MonetaryAmounts.getAmountTypes()) { 610 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 611 f.setCurrency("CHF"); 612 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 613 f.setNumber(BigDecimal.valueOf(0d)).create() 614 .isGreaterThanOrEqualTo(f.setNumber(BigDecimal.valueOf(0)).create())); 615 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 616 f.setNumber(BigDecimal.valueOf(0.00001d)).create() 617 .isGreaterThanOrEqualTo(f.setNumber(BigDecimal.valueOf(0d)).create())); 618 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 619 f.setNumber(15).create().isGreaterThanOrEqualTo(f.setNumber(10).create())); 620 AssertJUnit.assertTrue("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 621 f.setNumber(15.546).create().isGreaterThanOrEqualTo(f.setNumber(10.34).create())); 622 AssertJUnit.assertFalse("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 623 f.setNumber(5).create().isGreaterThanOrEqualTo(f.setNumber(10).create())); 624 AssertJUnit.assertFalse("Section 4.2.2: isGreaterThanOrEqualTo failed for " + type.getName(), 625 f.setNumber(5.546).create().isGreaterThanOrEqualTo(f.setNumber(10.34).create())); 626 } 627 } 628 629 /** 630 * Test isLessThan() is implemented correctly for each amount type regardless of trailing 631 * zeroes. 632 */ 633 @SpecAssertion(section = "4.2.2", id = "422-C3") 634 @Test(description = "4.2.2 For each amount class, check isLessThan().") 635 public void testMonetaryAmount_isLessThan() { 636 for (Class type : MonetaryAmounts.getAmountTypes()) { 637 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 638 f.setCurrency("CHF"); 639 AssertJUnit.assertFalse("Section 4.2.2: isLessThan failed for " + type.getName(), 640 f.setNumber(BigDecimal.valueOf(0d)).create() 641 .isLessThan(f.setNumber(BigDecimal.valueOf(0)).create())); 642 AssertJUnit.assertFalse("Section 4.2.2: isLessThan failed for " + type.getName(), 643 f.setNumber(BigDecimal.valueOf(0.00001d)).create() 644 .isLessThan(f.setNumber(BigDecimal.valueOf(0d)).create())); 645 AssertJUnit.assertFalse("Section 4.2.2: isLessThan failed for " + type.getName(), 646 f.setNumber(15).create().isLessThan(f.setNumber(10).create())); 647 AssertJUnit.assertFalse("Section 4.2.2: isLessThan failed for " + type.getName(), 648 f.setNumber(15.546).create().isLessThan(f.setNumber(10.34).create())); 649 AssertJUnit.assertTrue("Section 4.2.2: isLessThan failed for " + type.getName(), 650 f.setNumber(5).create().isLessThan(f.setNumber(10).create())); 651 AssertJUnit.assertTrue("Section 4.2.2: isLessThan failed for " + type.getName(), 652 f.setNumber(5.546).create().isLessThan(f.setNumber(10.34).create())); 653 } 654 } 655 656 /** 657 * Test isLessThanOrEquals() is implemented correctly for each amount type regardless of trailing 658 * zeroes. 659 */ 660 @SpecAssertion(section = "4.2.2", id = "422-C4") 661 @Test(description = "4.2.2 For each amount class, check isLessThanOrEqualTo().") 662 public void testMonetaryAmount_isLessThanOrEqualTo() { 663 for (Class type : MonetaryAmounts.getAmountTypes()) { 664 if (type.equals(TestAmount.class)) { 665 continue; 666 } 667 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 668 f.setCurrency("CHF"); 669 AssertJUnit.assertTrue("Section 4.2.2: isLessThanOrEqualTo failed for " + type.getName(), 670 f.setNumber(BigDecimal.valueOf(0d)).create() 671 .isLessThanOrEqualTo(f.setNumber(BigDecimal.valueOf(0)).create())); 672 AssertJUnit.assertFalse("Section 4.2.2: isLessThanOrEqualTo failed for " + type.getName(), 673 f.setNumber(BigDecimal.valueOf(0.00001d)).create() 674 .isLessThanOrEqualTo(f.setNumber(BigDecimal.valueOf(0d)).create())); 675 AssertJUnit.assertFalse("Section 4.2.2: isLessThanOrEqualTo failed for " + type.getName(), 676 f.setNumber(15).create().isLessThanOrEqualTo(f.setNumber(10).create())); 677 AssertJUnit.assertFalse("Section 4.2.2: isLessThan failed for " + type.getName(), 678 f.setNumber(15.546).create().isLessThan(f.setNumber(10.34).create())); 679 AssertJUnit.assertTrue("Section 4.2.2: isLessThanOrEqualTo failed for " + type.getName(), 680 f.setNumber(5).create().isLessThanOrEqualTo(f.setNumber(10).create())); 681 AssertJUnit.assertTrue("Section 4.2.2: isLessThanOrEqualTo failed for " + type.getName(), 682 f.setNumber(5.546).create().isLessThanOrEqualTo(f.setNumber(10.34).create())); 683 } 684 } 685 686 /** 687 * Test isEqualTo() is implemented correctly for each amount type regardless of trailing 688 * zeroes. 689 */ 690 @SpecAssertion(section = "4.2.2", id = "422-C5") 691 @Test(description = "4.2.2 For each amount class, check isEqualTo().") 692 public void testMonetaryAmount_isEqualTo() { 693 for (Class type : MonetaryAmounts.getAmountTypes()) { 694 if (type.equals(TestAmount.class)) { 695 continue; 696 } 697 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 698 f.setCurrency("CHF"); 699 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 700 f.setNumber(BigDecimal.valueOf(0d)).create() 701 .isEqualTo(f.setNumber(BigDecimal.valueOf(0)).create())); 702 AssertJUnit.assertFalse("Section 4.2.2: isEqualTo failed for " + type.getName(), 703 f.setNumber(BigDecimal.valueOf(0.00001d)).create() 704 .isEqualTo(f.setNumber(BigDecimal.valueOf(0d)).create())); 705 AssertJUnit.assertTrue("isEqualTo failed for " + type.getName(), 706 f.setNumber(BigDecimal.valueOf(5d)).create() 707 .isEqualTo(f.setNumber(BigDecimal.valueOf(5)).create())); 708 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 709 f.setNumber(BigDecimal.valueOf(1d)).create() 710 .isEqualTo(f.setNumber(BigDecimal.valueOf(1.00)).create())); 711 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 712 f.setNumber(BigDecimal.valueOf(1d)).create() 713 .isEqualTo(f.setNumber(BigDecimal.ONE).create())); 714 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 715 f.setNumber(BigDecimal.valueOf(1)).create() 716 .isEqualTo(f.setNumber(BigDecimal.ONE).create())); 717 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 718 f.setNumber(new BigDecimal("1.0000")).create() 719 .isEqualTo(f.setNumber(new BigDecimal("1.00")).create())); 720 // Test with different scales, but numeric equal values 721 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 722 f.setNumber(BigDecimal.valueOf(0d)).create() 723 .isEqualTo(f.setNumber(BigDecimal.valueOf(0)).create())); 724 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 725 f.setNumber(BigDecimal.ZERO).create() 726 .isEqualTo(f.setNumber(BigDecimal.valueOf(0)).create())); 727 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 728 f.setNumber(BigDecimal.valueOf(5)).create() 729 .isEqualTo(f.setNumber(new BigDecimal("5.0")).create())); 730 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 731 f.setNumber(BigDecimal.valueOf(5)).create() 732 .isEqualTo(f.setNumber(new BigDecimal("5.00")).create())); 733 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 734 f.setNumber(BigDecimal.valueOf(5)).create() 735 .isEqualTo(f.setNumber(new BigDecimal("5.000")).create())); 736 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 737 f.setNumber(BigDecimal.valueOf(5)).create() 738 .isEqualTo(f.setNumber(new BigDecimal("5.0000")).create())); 739 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 740 f.setNumber(new BigDecimal("-1.23")).create() 741 .isEqualTo(f.setNumber(new BigDecimal("-1.23")).create())); 742 try { 743 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 744 f.setNumber(new BigDecimal("-1.23")).create() 745 .isEqualTo(f.setNumber(new BigDecimal("-1.230")).create())); 746 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 747 f.setNumber(new BigDecimal("-1.23")).create() 748 .isEqualTo(f.setNumber(new BigDecimal("-1.2300")).create())); 749 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 750 f.setNumber(new BigDecimal("-1.23")).create() 751 .isEqualTo(f.setNumber(new BigDecimal("-1.23000")).create())); 752 AssertJUnit.assertTrue("Section 4.2.2: isEqualTo failed for " + type.getName(), 753 f.setNumber(new BigDecimal("-1.23")).create().isEqualTo( 754 f.setNumber(new BigDecimal("-1.230000000000000000000")).create())); 755 } catch (MonetaryException e) { 756 // happens if we exceed the limits... 757 } 758 } 759 } 760 761 /** 762 * For two amounts with same numeric value and currency: 763 * {@code }isEqualTo()} return true, regardless of MonetaryContext. 764 */ 765 @SpecAssertion(section = "4.2.2", id = "422-C6") 766 @Test(description = "4.2.2 For each amount class, check isEqualTo(), regardless different MonetaryContext " + 767 "instances.") 768 public void testMonetaryAmount_isEqualToRegardlessMonetaryContext() { 769 for (Class type : MonetaryAmounts.getAmountTypes()) { 770 if (type.equals(TestAmount.class)) { 771 continue; 772 } 773 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 774 MonetaryContext mc1 = f.getDefaultMonetaryContext(); 775 MonetaryContext mc2 = f.getMaximalMonetaryContext(); 776 MonetaryAmount m1; 777 MonetaryAmount m2; 778 if (mc1.equals(mc2)) { 779 // In this cases both amount must be equals 780 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10).create(); 781 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10).create(); 782 AssertJUnit.assertEquals("Section 4.2.2: m1.equals(m2) must be true for m1=" + m1 + " and m2=" + m2, m1, 783 m2); 784 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10.5d).create(); 785 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10.5d).create(); 786 AssertJUnit.assertEquals("Section 4.2.2: m1.equals(m2) must be true for m1=" + m1 + " and m2=" + m2, m1, 787 m2); 788 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(BigDecimal.TEN).create(); 789 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(BigDecimal.TEN).create(); 790 AssertJUnit.assertEquals("Section 4.2.2: m1.equals(m2) must be true for m1=" + m1 + " and m2=" + m2, m1, 791 m2); 792 } else { 793 // In this cases both amount must be non equals 794 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10).create(); 795 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10).create(); 796 AssertJUnit 797 .assertNotSame("Section 4.2.2: m1.equals(m2) must be false for m1=" + m1 + " and m2=" + m2, m1, 798 m2); 799 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m1 + " and m2=" + m2, 800 m1.isEqualTo(m2)); 801 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m2 + " and m2=" + m1, 802 m2.isEqualTo(m1)); 803 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(10.5d).create(); 804 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(10.5d).create(); 805 AssertJUnit 806 .assertNotSame("Section 4.2.2: m1.equals(m2) must be false for m1=" + m1 + " and m2=" + m2, m1, 807 m2); 808 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m1 + " and m2=" + m2, 809 m1.isEqualTo(m2)); 810 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m2 + " and m2=" + m1, 811 m2.isEqualTo(m1)); 812 m1 = f.setCurrency("CHF").setContext(mc1).setNumber(BigDecimal.TEN).create(); 813 m2 = f.setCurrency("CHF").setContext(mc2).setNumber(BigDecimal.TEN).create(); 814 AssertJUnit 815 .assertNotSame("Section 4.2.2: m1.equals(m2) must be false for m1=" + m1 + " and m2=" + m2, m1, 816 m2); 817 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m1 + " and m2=" + m2, 818 m1.isEqualTo(m2)); 819 AssertJUnit.assertTrue("Section 4.2.2: m1.isEqualTo(m2) must be true for m1=" + m2 + " and m2=" + m1, 820 m2.isEqualTo(m1)); 821 } 822 AssertJUnit.assertTrue("Section 4.2.2: m.isEqualTo(m) must be true for " + m1, m1.isEqualTo(m1)); 823 AssertJUnit.assertTrue("Section 4.2.2: m.isEqualTo(m) must be true for " + m2, m2.isEqualTo(m2)); 824 } 825 } 826 827 /** 828 * For two amounts with same numeric value and currency: 829 * {@code }isEqualTo()} return true, regardless of iumplementation type. 830 */ 831 @SpecAssertion(section = "4.2.2", id = "422-C7") 832 @Test(description = "4.2.2 For each amount class, check isEqualTo(), regardless implementation type.") 833 public void testMonetaryAmount_isEqualToRegardlessType() { 834 List<MonetaryAmount> instances = new ArrayList<>(); 835 for (Class type : MonetaryAmounts.getAmountTypes()) { 836 MonetaryAmountFactory f = getAmountFactory(type); 837 f.setCurrency("CHF"); 838 instances.add(f.setNumber(10).create()); 839 instances.add(f.setNumber(10.0d).create()); 840 instances.add(f.setNumber(BigDecimal.TEN).create()); 841 } 842 // compare each other... 843 for (int i = 0; i < instances.size(); i++) { 844 for (int j = 0; j < instances.size(); j++) { 845 MonetaryAmount mi = instances.get(i); 846 MonetaryAmount mj = instances.get(j); 847 AssertJUnit 848 .assertTrue("Section 4.2.2: isEqualTo must be true for " + mi + " and " + mj, mi.isEqualTo(mj)); 849 } 850 } 851 } 852 853 /** 854 * Tests that add() correctly adds two values, using positive integers. 855 */ 856 @SpecAssertion(section = "4.2.2", id = "422-D1") 857 @Test(description = "4.2.2 For each amount class, check m1.add(m2), m1 >0, m2>0.") 858 public void testAddPositiveIntegers() { 859 for (Class type : MonetaryAmounts.getAmountTypes()) { 860 if (type.equals(TestAmount.class)) { 861 continue; 862 } 863 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 864 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(20).create(); 865 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 866 MonetaryAmount mExpectedResult = 867 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(30).create(); 868 AssertJUnit.assertEquals( 869 "Section 4.2.2: Adding two simple ammounts failed, " + mAmount1 + " + " + mAmount2 + " != " + 870 mExpectedResult, mExpectedResult, mActualResult); 871 } 872 } 873 874 /** 875 * Tests that add() correctly adds two values, using negative integers. 876 */ 877 @SpecAssertion(section = "4.2.2", id = "422-D1") 878 @Test(description = "4.2.2 For each amount class, check m1.add(m2), m1 <0, m2<0.") 879 public void testAddNegativeIntegers() { 880 for (Class type : MonetaryAmounts.getAmountTypes()) { 881 if (type.equals(TestAmount.class)) { 882 continue; 883 } 884 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 885 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-20).create(); 886 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 887 MonetaryAmount mExpectedResult = 888 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-30).create(); 889 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 890 } 891 } 892 893 /** 894 * Tests that add() correctly adds two values, using fractions. 895 */ 896 @SpecAssertion(section = "4.2.2", id = "422-D1") 897 @Test(description = "4.2.2 For each amount class, check m1.add(m2), m2 is fraction.") 898 public void testAddPositiveFractions() { 899 for (Class type : MonetaryAmounts.getAmountTypes()) { 900 if (type.equals(TestAmount.class)) { 901 continue; 902 } 903 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(1.5).create(); 904 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(2.85).create(); 905 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 906 MonetaryAmount mExpectedResult = 907 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(4.35).create(); 908 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 909 } 910 } 911 912 /** 913 * Tests that add() correctly adds two values, using positive and negative integers. 914 */ 915 @SpecAssertion(section = "4.2.2", id = "422-D1") 916 @Test(description = "4.2.2 For each amount class, check m1.add(m2), m1, m2 = mixed ints.") 917 public void testAddMixedIntegers() { 918 for (Class type : MonetaryAmounts.getAmountTypes()) { 919 if (type.equals(TestAmount.class)) { 920 continue; 921 } 922 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 923 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(20).create(); 924 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 925 MonetaryAmount mExpectedResult = 926 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 927 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 928 } 929 for (Class type : MonetaryAmounts.getAmountTypes()) { 930 if (type.equals(TestAmount.class)) { 931 continue; 932 } 933 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-20).create(); 934 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 935 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 936 MonetaryAmount mExpectedResult = 937 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 938 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 939 } 940 for (Class type : MonetaryAmounts.getAmountTypes()) { 941 if (type.equals(TestAmount.class)) { 942 continue; 943 } 944 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 945 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 946 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 947 MonetaryAmount mExpectedResult = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 948 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 949 } 950 } 951 952 /** 953 * Tests that add() correctly adds two values, using positive and negative fractions. 954 */ 955 @SpecAssertion(section = "4.2.2", id = "422-D1") 956 @Test(description = "4.2.2 For each amount class, check m1.add(m2), m1, m2 = mixed fractions.") 957 public void testAddMixedFractions() { 958 for (Class type : MonetaryAmounts.getAmountTypes()) { 959 if (type.equals(TestAmount.class)) { 960 continue; 961 } 962 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(1.5).create(); 963 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-2.85).create(); 964 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 965 MonetaryAmount mExpectedResult = 966 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-1.35).create(); 967 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 968 } 969 for (Class type : MonetaryAmounts.getAmountTypes()) { 970 if (type.equals(TestAmount.class)) { 971 continue; 972 } 973 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-1.5).create(); 974 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(+2.85).create(); 975 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 976 MonetaryAmount mExpectedResult = 977 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(1.35).create(); 978 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 979 } 980 for (Class type : MonetaryAmounts.getAmountTypes()) { 981 if (type.equals(TestAmount.class)) { 982 continue; 983 } 984 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-2.85).create(); 985 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(+2.85).create(); 986 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 987 MonetaryAmount mExpectedResult = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 988 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 989 } 990 } 991 992 /** 993 * Tests that add() with non matching currencies throws a 994 * MonetaryException. 995 */ 996 @SpecAssertion(section = "4.2.2", id = "422-D2") 997 @Test(description = "4.2.2 For each amount class, ensure currency compatibility is working.") 998 public void testAdd_IncompatibleCurrencies() { 999 for (Class type : MonetaryAmounts.getAmountTypes()) { 1000 if (type.equals(TestAmount.class)) { 1001 continue; 1002 } 1003 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1004 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(ADDITIONAL_CURRENCY).setNumber(20).create(); 1005 try { 1006 mAmount1.add(mAmount2); 1007 AssertJUnit.fail("Section 4.2.2: Exception expected"); 1008 } catch (MonetaryException ex) { 1009 // Expected 1010 } 1011 } 1012 } 1013 1014 /** 1015 * Tests that add(0) should return itself. 1016 */ 1017 @SpecAssertion(section = "4.2.2", id = "422-D3") 1018 @Test(description = "4.2.2 For each amount class, ensure m2 = m1,add(0) -> m1==m2.") 1019 public void testAdd_Zero() { 1020 for (Class type : MonetaryAmounts.getAmountTypes()) { 1021 if (type.equals(TestAmount.class)) { 1022 continue; 1023 } 1024 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1025 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 1026 MonetaryAmount mActualResult = mAmount1.add(mAmount2); 1027 AssertJUnit.assertEquals("Section 4.2.2: Adding zero", mAmount1, mActualResult); 1028 } 1029 } 1030 1031 /** 1032 * Tests that add(), which results in an amount exceeding the max MonetaryContext throws 1033 * a MonetaryException. 1034 */ 1035 @SpecAssertion(section = "4.2.2", id = "422-D4") 1036 @Test(description = "4.2.2 For each amount class, ensure ArithemticException is thrown when adding exceeding " + 1037 "values.") 1038 public void testAdd_ExceedsCapabilities() { 1039 for (Class type : MonetaryAmounts.getAmountTypes()) { 1040 if (type.equals(TestAmount.class)) { 1041 continue; 1042 } 1043 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 1044 f.setCurrency("CHF"); 1045 MonetaryContext maxCtx = f.getMaximalMonetaryContext(); 1046 if (maxCtx.getPrecision() > 0) { 1047 MonetaryAmount m = f.setNumber(f.getMaxNumber()).create(); 1048 MonetaryAmount ms = m; 1049 try { 1050 for (int i = 0; i < 20; i++) { 1051 ms = ms.add(ms); 1052 } 1053 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected, since adding 20x " + m + " to " + m + 1054 " exceeds capabilities (precision) for " + 1055 type.getName()); 1056 } catch (ArithmeticException ex) { 1057 // Expected 1058 } catch (Exception e) { 1059 AssertJUnit.fail("Section 4.2.2: Addition of amount " + ms + " to " + ms + 1060 " exceeds max monetary context(scale), " + 1061 "but did not throw an ArithmeticException (exception thrown was " + 1062 e.getClass().getName() + "), type was " + 1063 type); 1064 } 1065 } 1066 } 1067 for (Class type : MonetaryAmounts.getAmountTypes()) { 1068 if (type.equals(TestAmount.class)) { 1069 continue; 1070 } 1071 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 1072 f.setCurrency("CHF"); 1073 MonetaryContext maxCtx = f.getMaximalMonetaryContext(); 1074 if (maxCtx.getMaxScale() >= 0) { 1075 try { 1076 MonetaryAmount m = f.setNumber(1).create(); 1077 MonetaryAmount m2 = 1078 f.setNumber(TestUtils.createNumberWithScale(f, maxCtx.getMaxScale() + 5)).create(); 1079 m.add(m2); 1080 AssertJUnit.fail("Section 4.2.2: Exception expected, since adding " + m2 + " to " + m + 1081 " exceeds capabilities (scale) for " + 1082 type.getName()); 1083 } catch (ArithmeticException ex) { 1084 // Expected 1085 } 1086 } 1087 } 1088 } 1089 1090 1091 /** 1092 * Tests that add(), which results in an amount exceeding the max MonetaryContext throws 1093 * a MonetaryException. 1094 */ 1095 @SpecAssertion(section = "4.2.2", id = "422-D5") 1096 @Test(description = "4.2.2 For each amount class, ensure NullPointerException is thrown when calling m.add(null).") 1097 public void testAdd_Null() { 1098 for (Class type : MonetaryAmounts.getAmountTypes()) { 1099 if (type.equals(TestAmount.class)) { 1100 continue; 1101 } 1102 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1103 try { 1104 MonetaryAmount mActualResult = mAmount1.add(null); 1105 AssertJUnit.fail("Section 4.2.2: MonetaryAmount.add(null): NullPointerException expected"); 1106 } catch (NullPointerException ex) { 1107 // Expected 1108 } 1109 } 1110 } 1111 1112 1113 /** 1114 * Tests that subtract() correctly adds two values, using positive integers. 1115 */ 1116 @SpecAssertion(section = "4.2.2", id = "422-D6") 1117 @Test(description = "4.2.2 For each amount class, ensure correct subtraction of positive ints.") 1118 public void testSubtractPositiveIntegers() { 1119 for (Class type : MonetaryAmounts.getAmountTypes()) { 1120 if (type.equals(TestAmount.class)) { 1121 continue; 1122 } 1123 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1124 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(20).create(); 1125 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1126 MonetaryAmount mExpectedResult = 1127 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 1128 AssertJUnit.assertEquals("Section 4.2.2: Subtracting two simple ammounts", mExpectedResult, mActualResult); 1129 } 1130 } 1131 1132 /** 1133 * Tests that subtract() correctly adds two values, using negative integers. 1134 */ 1135 @SpecAssertion(section = "4.2.2", id = "422-D6") 1136 @Test(description = "4.2.2 For each amount class, ensure correct subtraction of negative ints.") 1137 public void testSubtractNegativeIntegers() { 1138 for (Class type : MonetaryAmounts.getAmountTypes()) { 1139 if (type.equals(TestAmount.class)) { 1140 continue; 1141 } 1142 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 1143 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-20).create(); 1144 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1145 MonetaryAmount mExpectedResult = 1146 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1147 AssertJUnit.assertEquals("Section 4.2.2: Subtracting two simple ammounts", mExpectedResult, mActualResult); 1148 } 1149 } 1150 1151 /** 1152 * Tests that subtract() correctly adds two values, using fractions. 1153 */ 1154 @SpecAssertion(section = "4.2.2", id = "422-D6") 1155 @Test(description = "4.2.2 For each amount class, ensure correct subtraction of positive fractions.") 1156 public void testSubtractPositiveFractions() { 1157 for (Class type : MonetaryAmounts.getAmountTypes()) { 1158 if (type.equals(TestAmount.class)) { 1159 continue; 1160 } 1161 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(1.5).create(); 1162 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(2.85).create(); 1163 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1164 MonetaryAmount mExpectedResult = 1165 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-1.35).create(); 1166 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1167 } 1168 } 1169 1170 /** 1171 * Tests that subtract() correctly adds two values, using positive and negative integers. 1172 */ 1173 @SpecAssertion(section = "4.2.2", id = "422-D6") 1174 @Test(description = "4.2.2 For each amount class, ensure correct subtraction of mixed ints.") 1175 public void testSubtractMixedIntegers() { 1176 for (Class type : MonetaryAmounts.getAmountTypes()) { 1177 if (type.equals(TestAmount.class)) { 1178 continue; 1179 } 1180 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(20).create(); 1181 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1182 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1183 MonetaryAmount mExpectedResult = 1184 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1185 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1186 } 1187 for (Class type : MonetaryAmounts.getAmountTypes()) { 1188 if (type.equals(TestAmount.class)) { 1189 continue; 1190 } 1191 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1192 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1193 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1194 MonetaryAmount mExpectedResult = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 1195 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1196 } 1197 for (Class type : MonetaryAmounts.getAmountTypes()) { 1198 if (type.equals(TestAmount.class)) { 1199 continue; 1200 } 1201 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-10).create(); 1202 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1203 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1204 MonetaryAmount mExpectedResult = 1205 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-20).create(); 1206 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1207 } 1208 } 1209 1210 /** 1211 * Tests that subtract() correctly adds two values, using positive and negative fractions. 1212 */ 1213 @SpecAssertion(section = "4.2.2", id = "422-D6") 1214 @Test(description = "4.2.2 For each amount class, ensure correct subtraction of mixed fractions.") 1215 public void testSubtractMixedFractions() { 1216 for (Class type : MonetaryAmounts.getAmountTypes()) { 1217 if (type.equals(TestAmount.class)) { 1218 continue; 1219 } 1220 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(1.5).create(); 1221 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-2.85).create(); 1222 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1223 MonetaryAmount mExpectedResult = 1224 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(4.35).create(); 1225 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1226 } 1227 for (Class type : MonetaryAmounts.getAmountTypes()) { 1228 if (type.equals(TestAmount.class)) { 1229 continue; 1230 } 1231 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-1.5).create(); 1232 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(+2.85).create(); 1233 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1234 MonetaryAmount mExpectedResult = 1235 getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(-4.35).create(); 1236 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1237 } 1238 for (Class type : MonetaryAmounts.getAmountTypes()) { 1239 if (type.equals(TestAmount.class)) { 1240 continue; 1241 } 1242 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(2.85).create(); 1243 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(+2.85).create(); 1244 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1245 MonetaryAmount mExpectedResult = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 1246 AssertJUnit.assertEquals("Section 4.2.2: Adding two simple ammounts", mExpectedResult, mActualResult); 1247 } 1248 } 1249 1250 /** 1251 * Tests that subtract() with non matching currencies throws a 1252 * MonetaryException. 1253 */ 1254 @SpecAssertion(section = "4.2.2", id = "422-D8") 1255 @Test(description = "4.2.2 For each amount class, ensure subtraction with invalid currency throws " + 1256 "MonetaryException.") 1257 public void testSubtract_IncompatibleCurrencies() { 1258 for (Class type : MonetaryAmounts.getAmountTypes()) { 1259 if (type.equals(TestAmount.class)) { 1260 continue; 1261 } 1262 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1263 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(ADDITIONAL_CURRENCY).setNumber(20).create(); 1264 try { 1265 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1266 AssertJUnit.fail("Section 4.2.2: Exception expected"); 1267 } catch (MonetaryException ex) { 1268 // Expected 1269 } 1270 } 1271 } 1272 1273 /** 1274 * Tests that subtract(0) should return itself. 1275 */ 1276 @SpecAssertion(section = "4.2.2", id = "422-D7") 1277 @Test(description = "4.2.2 For each amount class, ensure subtraction of 0 returns same instance.") 1278 public void testSubtract_Zero() { 1279 for (Class type : MonetaryAmounts.getAmountTypes()) { 1280 if (type.equals(TestAmount.class)) { 1281 continue; 1282 } 1283 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1284 MonetaryAmount mAmount2 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 1285 MonetaryAmount mActualResult = mAmount1.subtract(mAmount2); 1286 AssertJUnit.assertEquals("Section 4.2.2: Subtract zero", mAmount1, mActualResult); 1287 } 1288 } 1289 1290 /** 1291 * Tests that subtract(), which results in an amount exceeding the max MonetaryContext throws 1292 * a MonetaryException. 1293 */ 1294 @SpecAssertion(section = "4.2.2", id = "422-D9") 1295 @Test(description = "4.2.2 For each amount class, ensure subtraction with exceeding capabilities throws " + 1296 "ArithmeticException.") 1297 public void testSubtract_ExceedsCapabilities() { 1298 for (Class type : MonetaryAmounts.getAmountTypes()) { 1299 if (type.equals(TestAmount.class)) { 1300 continue; 1301 } 1302 MonetaryAmountFactory f = getAmountFactory(type); 1303 f.setCurrency("CHF"); 1304 MonetaryContext maxCtx = f.getMaximalMonetaryContext(); 1305 MonetaryAmount m = null; 1306 if (maxCtx.getPrecision() > 0) { 1307 MonetaryAmount mAmount1 = null; 1308 try { 1309 mAmount1 = f.setNumber(f.getMinNumber()).create().negate(); 1310 m = TestUtils.createAmountWithPrecision(maxCtx.getPrecision() + 1); 1311 mAmount1 = mAmount1.subtract(m); 1312 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected on subtraction that exceeds " + 1313 "capabilities for " + 1314 type.getName()); 1315 } catch (ArithmeticException ex) { 1316 // Expected 1317 } catch (Exception e) { 1318 AssertJUnit.fail("Section 4.2.2: Subtraction of amount " + m + " from " + mAmount1 + 1319 " exceeds max monetary context(scale), " + 1320 "but did not throw an ArithmeticException (exception thrown was " + 1321 e.getClass().getName() + "), type was " + 1322 type); 1323 } 1324 } 1325 } 1326 1327 for (Class type : MonetaryAmounts.getAmountTypes()) { 1328 if (type.equals(TestAmount.class)) { 1329 continue; 1330 } 1331 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 1332 f.setCurrency("CHF"); 1333 MonetaryAmount mAmount1 = f.setNumber(0).create(); 1334 MonetaryContext maxCtx = f.getMaximalMonetaryContext(); 1335 MonetaryAmount m = null; 1336 if (maxCtx.getMaxScale() >= 0) { 1337 m = TestUtils.createAmountWithScale(maxCtx.getMaxScale() + 1); 1338 } 1339 if (m != null) { 1340 try { 1341 mAmount1.subtract(m); 1342 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected on subtraction that exceeds " + 1343 "capabilities for " + 1344 type.getName()); 1345 } catch (ArithmeticException ex) { 1346 // Expected 1347 } catch (Exception e) { 1348 AssertJUnit.fail("Section 4.2.2: Subtraction of amount " + m + " from " + mAmount1 + 1349 " exceeds max monetary context(scale), " + 1350 "but did not throw an ArithmeticException (exception thrown was " + 1351 e.getClass().getName() + "), type was " + 1352 type); 1353 } 1354 } 1355 } 1356 } 1357 1358 /** 1359 * Tests that subtract(), which results in an amount exceeding the max MonetaryContext throws 1360 * a MonetaryException. 1361 */ 1362 @SpecAssertion(section = "4.2.2", id = "422-D10") 1363 @Test(description = "4.2.2 For each amount class, ensure subtraction with null throws NullPointerException.") 1364 public void testSubtract_Null() { 1365 for (Class type : MonetaryAmounts.getAmountTypes()) { 1366 if (type.equals(TestAmount.class)) { 1367 continue; 1368 } 1369 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1370 try { 1371 mAmount1.subtract(null); 1372 AssertJUnit.fail("Section 4.2.2: MonetaryAmount.subtract(null): NullPointerException expected"); 1373 } catch (NullPointerException ex) { 1374 // Expected 1375 } 1376 } 1377 } 1378 1379 /** 1380 * Test multiply() allow to multiply numbers. 1381 */ 1382 @SpecAssertion(section = "4.2.2", id = "422-D11") 1383 @Test(description = "4.2.2 For each amount class, ensure correct multiplication of int values.") 1384 public void testMultiply_Integral() { 1385 for (Class type : MonetaryAmounts.getAmountTypes()) { 1386 if (type.equals(TestAmount.class)) { 1387 continue; 1388 } 1389 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1390 MonetaryAmount mActualResult = mAmount1.multiply(2L); 1391 AssertJUnit.assertTrue( 1392 "Section 4.2.2: Multiplication with 2 does not return correct value for " + type.getName(), 1393 mActualResult.getNumber().longValueExact() == 20); 1394 mActualResult = mAmount1.multiply(Double.valueOf(-3)); 1395 AssertJUnit.assertTrue( 1396 "Section 4.2.2: Multiplication with -3 does not return correct value for " + type.getName(), 1397 mActualResult.getNumber().longValueExact() == -30); 1398 mActualResult = mAmount1.multiply(BigDecimal.ONE); 1399 AssertJUnit.assertTrue( 1400 "Section 4.2.2: Multiplication with 1 does not return correct value for " + type.getName(), 1401 mActualResult.getNumber().longValueExact() == 10); 1402 AssertJUnit.assertTrue( 1403 "Section 4.2.2: Multiplication with 1 does not return identity value for " + type.getName(), 1404 mActualResult == mAmount1); 1405 mActualResult = mAmount1.multiply(BigDecimal.ZERO); 1406 AssertJUnit.assertTrue( 1407 "Section 4.2.2: Multiplication with 0 does not return correct value for " + type.getName(), 1408 mActualResult.getNumber().longValueExact() == 0); 1409 } 1410 } 1411 1412 /** 1413 * Test multiply() allow to multiply numbers. 1414 */ 1415 @SpecAssertion(section = "4.2.2", id = "422-D11") 1416 @Test(description = "4.2.2 For each amount class, ensure correct multiplication of decimal values.") 1417 public void testMultiply_Decimals() { 1418 for (Class type : MonetaryAmounts.getAmountTypes()) { 1419 if (type.equals(TestAmount.class)) { 1420 continue; 1421 } 1422 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1423 MonetaryAmount mActualResult = mAmount1.multiply(1.5d); 1424 AssertJUnit.assertTrue( 1425 "Section 4.2.2: Multiplication with 1.5 does not return correct value for " + type.getName(), 1426 mActualResult.getNumber().longValueExact() == 15); 1427 mActualResult = mAmount1.multiply(Double.valueOf(-1.5)); 1428 AssertJUnit.assertTrue( 1429 "Section 4.2.2: Multiplication with -3 does not return correct value for " + type.getName(), 1430 mActualResult.getNumber().longValueExact() == -15); 1431 mActualResult = mAmount1.multiply(0.0); 1432 AssertJUnit.assertTrue( 1433 "Section 4.2.2: Multiplication with 0 does not return correct value for " + type.getName(), 1434 mActualResult.getNumber().longValueExact() == 0); 1435 mActualResult = mAmount1.multiply(1.0); 1436 AssertJUnit.assertTrue( 1437 "Section 4.2.2: Multiplication with 0 does not return correct value for " + type.getName(), 1438 mActualResult.getNumber().longValueExact() == 10); 1439 AssertJUnit.assertTrue( 1440 "Section 4.2.2: Multiplication with 0 does not return identity value for " + type.getName(), 1441 mActualResult == mAmount1); 1442 } 1443 } 1444 1445 /** 1446 * Test multiply(1) returns this. 1447 */ 1448 @SpecAssertion(section = "4.2.2", id = "422-D12") 1449 @Test(description = "4.2.2 For each amount class, ensure multiplication by one returns same instance.") 1450 public void testMultiplyOne() { 1451 for (Class type : MonetaryAmounts.getAmountTypes()) { 1452 if (type.equals(TestAmount.class)) { 1453 continue; 1454 } 1455 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1456 MonetaryAmount mActualResult = mAmount1.multiply(1); 1457 AssertJUnit.assertTrue( 1458 "Section 4.2.2: Multiplication with 1 does not return identity value for " + type.getName(), 1459 mActualResult == mAmount1); 1460 mActualResult = mAmount1.multiply(1.0); 1461 AssertJUnit.assertTrue( 1462 "Section 4.2.2: Multiplication with 1 does not return identity value for " + type.getName(), 1463 mActualResult == mAmount1); 1464 mActualResult = mAmount1.multiply(BigDecimal.ONE); 1465 AssertJUnit.assertTrue( 1466 "Section 4.2.2: Multiplication with 1 does not return identity value for " + type.getName(), 1467 mActualResult == mAmount1); 1468 } 1469 } 1470 1471 1472 /** 1473 * Test multiply, which results in an amount exceeding the max 1474 * MonetaryContext must throw a 1475 * ArithmeticException. 1476 */ 1477 @SpecAssertion(section = "4.2.2", id = "422-D13") 1478 @Test(description = "4.2.2 For each amount class, ensure multiplication with exceeding values throws " + 1479 "ArithmeticException.") 1480 public void testMultiplyExceedsCapabilities() { 1481 for (Class type : MonetaryAmounts.getAmountTypes()) { 1482 if (type.equals(TestAmount.class)) { 1483 continue; 1484 } 1485 MonetaryAmountFactory<?> f = getAmountFactory(type); 1486 MonetaryContext ctx = f.getMaximalMonetaryContext(); 1487 if (ctx.getMaxScale() >= 0) { 1488 BigDecimal num = TestUtils.createNumberWithScale(f, ctx.getMaxScale() + 5); 1489 MonetaryAmount m = f.setNumber(10).setCurrency("USD").create(); 1490 try { 1491 m.multiply(num); 1492 } catch (ArithmeticException e) { 1493 // OK! 1494 } catch (Exception e) { 1495 AssertJUnit.fail("Section 4.2.2: Multiplication of amount 10 with " + num + 1496 " exceeds max monetary context(scale), should be rounded, " + 1497 "but did throw an Exception (exception thrown was " + 1498 e.getClass().getName() + "), type was " + 1499 type); 1500 } 1501 } 1502 } 1503 for (Class type : MonetaryAmounts.getAmountTypes()) { 1504 if (type.equals(TestAmount.class)) { 1505 continue; 1506 } 1507 MonetaryAmountFactory<?> f = getAmountFactory(type); 1508 MonetaryContext ctx = f.getMaximalMonetaryContext(); 1509 if (ctx.getPrecision() > 0) { 1510 BigDecimal num = TestUtils.createNumberWithPrecision(f, ctx.getPrecision() + 5); 1511 MonetaryAmount m = f.setNumber(10).setCurrency("USD").create(); 1512 try { 1513 m.multiply(num); 1514 AssertJUnit.fail("Section 4.2.2: Multiplication of amount " + num + 1515 " with 10000000 exceeds max monetary context(precision), " + 1516 "but did not throw an ArithmeticException, type was " + 1517 type.getName()); 1518 } catch (ArithmeticException e) { 1519 // OK 1520 } catch (Exception e) { 1521 AssertJUnit.fail("Section 4.2.2: Multiplication of amount " + num + 1522 " with 10000000 exceeds max monetary context(precision), " + 1523 "but did not throw an ArithmeticException (exception thrown was " + 1524 e.getClass().getName() + "), type was " + 1525 type.getName()); 1526 } 1527 } 1528 } 1529 } 1530 1531 /** 1532 * Test multiply(null) must throw an NullPointerException. 1533 */ 1534 @SpecAssertion(section = "4.2.2", id = "422-D14") 1535 @Test(description = "4.2.2 For each amount class, ensure multiplication of null throws NullPointerException.") 1536 public void testMultiplyNull() { 1537 for (Class type : MonetaryAmounts.getAmountTypes()) { 1538 if (type.equals(TestAmount.class)) { 1539 continue; 1540 } 1541 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1542 try { 1543 MonetaryAmount mActualResult = mAmount1.multiply(null); 1544 AssertJUnit 1545 .fail("Section 4.2.2: NullPointerException expected for multiplication with null, type was " + 1546 type.getName()); 1547 } catch (NullPointerException e) { 1548 // expected 1549 } 1550 } 1551 } 1552 1553 /** 1554 * Test multiply(Double.NaN) must throw an ArithmeticException. 1555 */ 1556 @SpecAssertion(section = "4.2.2", id = "422-D14") 1557 @Test(description = "4.2.2 For each amount class, ensure multiplication of Double.NaN throws ArithmeticException.") 1558 public void testMultiply_DoubleNaN() { 1559 for (Class type : MonetaryAmounts.getAmountTypes()) { 1560 if (type.equals(TestAmount.class)) { 1561 continue; 1562 } 1563 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1564 try { 1565 MonetaryAmount mActualResult = mAmount1.multiply(Double.NaN); 1566 AssertJUnit 1567 .fail("Section 4.2.2: ArithmeticException expected for multiplication with Double.NaN, type was " + 1568 type.getName()); 1569 } catch (ArithmeticException e) { 1570 // expected 1571 } 1572 } 1573 } 1574 1575 /** 1576 * Test multiply(Double.POSITIVE_INFINITY) must throw an ArithmeticException. 1577 */ 1578 @SpecAssertion(section = "4.2.2", id = "422-D14") 1579 @Test(description = "4.2.2 For each amount class, ensure multiplication of Double.POSITIVE_INFINITY throws ArithmeticException.") 1580 public void testMultiply_DoublePOSITIVE_INFINITY() { 1581 for (Class type : MonetaryAmounts.getAmountTypes()) { 1582 if (type.equals(TestAmount.class)) { 1583 continue; 1584 } 1585 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1586 try { 1587 MonetaryAmount mActualResult = mAmount1.multiply(Double.POSITIVE_INFINITY); 1588 AssertJUnit 1589 .fail("Section 4.2.2: ArithmeticException expected for multiplication with Double.POSITIVE_INFINITY, type was " + 1590 type.getName()); 1591 } catch (ArithmeticException e) { 1592 // expected 1593 } 1594 } 1595 } 1596 1597 /** 1598 * Test multiply(Double.POSITIVE_INFINITY) must throw an ArithmeticException. 1599 */ 1600 @SpecAssertion(section = "4.2.2", id = "422-D14") 1601 @Test(description = "4.2.2 For each amount class, ensure multiplication of Double.NEGATIVE_INFINITY throws ArithmeticException.") 1602 public void testMultiply_DoubleNEGATIVE_INFINITY() { 1603 for (Class type : MonetaryAmounts.getAmountTypes()) { 1604 if (type.equals(TestAmount.class)) { 1605 continue; 1606 } 1607 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1608 try { 1609 MonetaryAmount mActualResult = mAmount1.multiply(Double.NEGATIVE_INFINITY); 1610 AssertJUnit 1611 .fail("Section 4.2.2: ArithmeticException expected for multiplication with Double.NEGATIVE_INFINITY, type was " + 1612 type.getName()); 1613 } catch (ArithmeticException e) { 1614 // expected 1615 } 1616 } 1617 } 1618 1619 /** 1620 * Test divide() function allow to divide numbers. 1621 */ 1622 @SpecAssertion(section = "4.2.2", id = "422-D15") 1623 @Test(description = "4.2.2 For each amount class, ensure correct division.") 1624 public void testDivide() { 1625 for (Class type : MonetaryAmounts.getAmountTypes()) { 1626 if (type.equals(TestAmount.class)) { 1627 continue; 1628 } 1629 MonetaryAmount m = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1630 MonetaryAmount m2 = m.divide(10); 1631 AssertJUnit.assertEquals("Section 4.2.2: Currency not equal after division, type was " + type.getName(), 1632 DEFAULT_CURRENCY, m2.getCurrency().getCurrencyCode()); 1633 AssertJUnit.assertEquals("Section 4.2.2: Division result is not correct for " + type.getName(), 1, 1634 m2.getNumber().longValueExact()); 1635 // TODO iterate over array of different numbers and divisors, use BD to check results 1636 } 1637 } 1638 1639 /** 1640 * Test divideToIntegralValue() function allow to divide numbers. 1641 */ 1642 @SpecAssertion(section = "4.2.2", id = "422-D15") 1643 @Test(description = "4.2.2 For each amount class, ensure correct division with int values.") 1644 public void testDivideToIntegralValue() { 1645 for (Class type : MonetaryAmounts.getAmountTypes()) { 1646 if (type.equals(TestAmount.class)) { 1647 continue; 1648 } 1649 CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR"); 1650 MonetaryAmount money1 = getAmountFactory(type).setNumber(BigDecimal.ONE).setCurrency(euro).create(); 1651 MonetaryAmount result = money1.divideToIntegralValue(new BigDecimal("0.5001")); 1652 AssertJUnit.assertEquals( 1653 "Section 4.2.2: divideToIntegralValue returned incorrect result for " + type.getName(), 1654 result.getNumber().numberValue(BigDecimal.class).stripTrailingZeros(), 1655 new BigDecimal("1.0").stripTrailingZeros()); 1656 result = money1.divideToIntegralValue(new BigDecimal("0.2001")); 1657 AssertJUnit.assertEquals( 1658 "Section 4.2.2: divideToIntegralValue returned incorrect result for " + type.getName(), 1659 result.getNumber().numberValue(BigDecimal.class).stripTrailingZeros(), 1660 new BigDecimal("4.0").stripTrailingZeros()); 1661 result = money1.divideToIntegralValue(new BigDecimal("5.0")); 1662 AssertJUnit 1663 .assertTrue("Section 4.2.2: divideToIntegralValue returned incorrect result for " + type.getName(), 1664 result.getNumber().numberValue(BigDecimal.class).intValueExact() == 0); 1665 } 1666 } 1667 1668 /** 1669 * Test divide(0) function must throw an ArithmeticException. 1670 */ 1671 @SpecAssertion(section = "4.2.2", id = "422-D16") 1672 @Test(description = "4.2.2 For each amount class, ensure divide(0) throws ArithmeticException.") 1673 public void testDivideZero() { 1674 for (Class type : MonetaryAmounts.getAmountTypes()) { 1675 if (type.equals(TestAmount.class)) { 1676 continue; 1677 } 1678 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1679 try { 1680 MonetaryAmount mActualResult = mAmount1.divide(0); 1681 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected on division by 0, type was " + 1682 type.getName()); 1683 } catch (ArithmeticException ex) { 1684 // expected 1685 } 1686 } 1687 } 1688 1689 /** 1690 * Test divide(0) function must throw an ArithmeticException. 1691 */ 1692 @SpecAssertion(section = "4.2.2", id = "422-D16") 1693 @Test(description = "4.2.2 For each amount class, ensure divide(Double.NaN) throws ArithmeticException.") 1694 public void testDivideDoubleNaN() { 1695 for (Class type : MonetaryAmounts.getAmountTypes()) { 1696 if (type.equals(TestAmount.class)) { 1697 continue; 1698 } 1699 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1700 try { 1701 MonetaryAmount mActualResult = mAmount1.divide(Double.NaN); 1702 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected on division by Double.NaN, type was " + 1703 type.getName()); 1704 } catch (ArithmeticException ex) { 1705 // expected 1706 } 1707 } 1708 } 1709 1710 /** 1711 * Test divide(0) function must return ZERO amount. 1712 */ 1713 @SpecAssertion(section = "4.2.2", id = "422-D16") 1714 @Test(description = "4.2.2 For each amount class, ensure divide(Double.POSITIVE_INFINITY) return ZERO amount.") 1715 public void testDivideDoublePOSITIVE_INFINITY() { 1716 for (Class type : MonetaryAmounts.getAmountTypes()) { 1717 if (type.equals(TestAmount.class)) { 1718 continue; 1719 } 1720 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1721 MonetaryAmount mActualResult = mAmount1.divide(Double.POSITIVE_INFINITY); 1722 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected on division by Double.POSITIVE_INFINITY, type was " + 1723 type.getName(), mActualResult, getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create()); 1724 } 1725 } 1726 1727 /** 1728 * Test divide(Double.NEGATIVE_INFINITY) function must return ZERO amount. 1729 */ 1730 @SpecAssertion(section = "4.2.2", id = "422-D16") 1731 @Test(description = "4.2.2 For each amount class, ensure divide(Double.NEGATIVE_INFINITY) return ZERO amount.") 1732 public void testDivideDoubleNEGATIVE_INFINITY() { 1733 for (Class type : MonetaryAmounts.getAmountTypes()) { 1734 if (type.equals(TestAmount.class)) { 1735 continue; 1736 } 1737 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1738 MonetaryAmount mActualResult = mAmount1.divide(Double.NEGATIVE_INFINITY); 1739 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected on division by Double.POSITIVE_INFINITY, type was " + 1740 type.getName(), mActualResult, getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create()); 1741 } 1742 } 1743 1744 /** 1745 * Test divide(1) should return this. 1746 */ 1747 @SpecAssertion(section = "4.2.2", id = "422-D17") 1748 @Test(description = "4.2.2 For each amount class, ensure divide 1 returns same instance.") 1749 public void testDivideOne() { 1750 for (Class type : MonetaryAmounts.getAmountTypes()) { 1751 if (type.equals(TestAmount.class)) { 1752 continue; 1753 } 1754 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1755 MonetaryAmount mActualResult = mAmount1.divide(1); 1756 AssertJUnit.assertTrue("Section 4.2.2: Division by 1 does not return identity value for " + type.getName(), 1757 mActualResult == mAmount1); 1758 mActualResult = mAmount1.divide(1.0); 1759 AssertJUnit.assertTrue("Section 4.2.2: Division by 1 does not return identity value for " + type.getName(), 1760 mActualResult == mAmount1); 1761 mActualResult = mAmount1.divide(BigDecimal.ONE); 1762 AssertJUnit.assertTrue("Section 4.2.2: Division by 1 does not return identity value for " + type.getName(), 1763 mActualResult == mAmount1); 1764 } 1765 } 1766 1767 /** 1768 * Test divide(null)must throw a NullPointerException. 1769 */ 1770 @SpecAssertion(section = "4.2.2", id = "422-D18") 1771 @Test(description = "4.2.2 For each amount class, ensure divide by null throws NullPointerException.") 1772 public void testDivideNull() { 1773 for (Class type : MonetaryAmounts.getAmountTypes()) { 1774 if (type.equals(TestAmount.class)) { 1775 continue; 1776 } 1777 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1778 try { 1779 MonetaryAmount mActualResult = mAmount1.divide(null); 1780 AssertJUnit.fail("Section 4.2.2: NullPointerException expected for division by null, type was " + 1781 type.getName()); 1782 } catch (NullPointerException e) { 1783 // expected 1784 } 1785 } 1786 } 1787 1788 /** 1789 * Test remainder()allow to calculate the remainder. 1790 */ 1791 @SpecAssertion(section = "4.2.2", id = "422-D19") 1792 @Test(description = "4.2.2 For each amount class, ensure correct results for remainder.") 1793 public void testRemainder() { 1794 for (Class type : MonetaryAmounts.getAmountTypes()) { 1795 if (type.equals(TestAmount.class)) { 1796 continue; 1797 } 1798 MonetaryAmountFactory<?> f = getAmountFactory(type); 1799 f.setCurrency("CHF"); 1800 MonetaryAmount[] moneys = new MonetaryAmount[]{f.setNumber(100).create(), f.setNumber(34242344).create(), 1801 f.setNumber(23123213.435).create(), f.setNumber(0).create(), f.setNumber(-100).create(), 1802 f.setNumber(-723527.36532).create()}; 1803 for (MonetaryAmount m : moneys) { 1804 AssertJUnit.assertEquals("Section 4.2.2: Invalid remainder of " + 10.50 + " for " + type.getName(), 1805 m.getFactory().setNumber(m.getNumber().numberValue(BigDecimal.class) 1806 .remainder(BigDecimal.valueOf(10.50))) 1807 .create(), m.remainder(10.50)); 1808 AssertJUnit.assertEquals("Section 4.2.2: Invalid remainder of " + -30.20 + " for " + type.getName(), 1809 m.getFactory().setNumber(m.getNumber().numberValue(BigDecimal.class) 1810 .remainder(BigDecimal.valueOf(-30.20))) 1811 .create(), m.remainder(-30.20)); 1812 AssertJUnit.assertEquals("Section 4.2.2: Invalid remainder of " + -3 + " for " + type.getName(), 1813 m.getFactory().setNumber(m.getNumber().numberValue(BigDecimal.class) 1814 .remainder(BigDecimal.valueOf(-3))).create(), 1815 m.remainder(-3)); 1816 AssertJUnit.assertEquals("Section 4.2.2: Invalid remainder of " + 3 + " for " + type.getName(), 1817 m.getFactory().setNumber(m.getNumber().numberValue(BigDecimal.class) 1818 .remainder(BigDecimal.valueOf(3))).create(), 1819 m.remainder(3)); 1820 } 1821 } 1822 } 1823 1824 /** 1825 * Test remainder(0) must throw an ArithmeticException 1826 */ 1827 @SpecAssertion(section = "4.2.2", id = "422-D20") 1828 @Test(description = "4.2.2 For each amount class, ensure remainder(0), double, throws ArithmeticException.") 1829 public void testRemainderZero_Double() { 1830 for (Class type : MonetaryAmounts.getAmountTypes()) { 1831 if (type.equals(TestAmount.class)) { 1832 continue; 1833 } 1834 MonetaryAmount m = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1835 try { 1836 m.remainder(0.0d); 1837 AssertJUnit 1838 .fail("Section 4.2.2: remainder(0) did not throw an ArithmeticException for " + type.getName()); 1839 } catch (ArithmeticException e) { 1840 // OK, ignore 1841 } catch (Exception e) { 1842 AssertJUnit.fail("Section 4.2.2: remainder(0.0d) did not throw an ArithmeticException for " + 1843 type.getName() + ", but " + 1844 e); 1845 } 1846 } 1847 } 1848 1849 /** 1850 * Test remainder(0) must throw an ArithmeticException 1851 */ 1852 @SpecAssertion(section = "4.2.2", id = "422-D20") 1853 @Test(description = "4.2.2 For each amount class, ensure remainder(0), long, throws ArithmeticException.") 1854 public void testRemainderZero_Long() { 1855 for (Class type : MonetaryAmounts.getAmountTypes()) { 1856 if (type.equals(TestAmount.class)) { 1857 continue; 1858 } 1859 MonetaryAmount m = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1860 try { 1861 m.remainder(0L); 1862 AssertJUnit.fail("Section 4.2.2: remainder(0L) did not throw an ArithmeticException for " + 1863 type.getName()); 1864 } catch (ArithmeticException e) { 1865 // OK, ignore 1866 } catch (Exception e) { 1867 AssertJUnit.fail("Section 4.2.2: remainder(0L) did not throw an ArithmeticException for " + 1868 type.getName() + ", but " + 1869 e); 1870 } 1871 } 1872 } 1873 1874 /** 1875 * Test remainder(0) must throw an ArithmeticException 1876 */ 1877 @SpecAssertion(section = "4.2.2", id = "422-D20") 1878 @Test(description = "4.2.2 For each amount class, ensure remainder(0), Number, throws ArithmeticException.") 1879 public void testRemainderZero_Number() { 1880 for (Class type : MonetaryAmounts.getAmountTypes()) { 1881 if (type.equals(TestAmount.class)) { 1882 continue; 1883 } 1884 MonetaryAmount m = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1885 try { 1886 m.remainder(BigDecimal.ZERO); 1887 AssertJUnit.fail("Section 4.2.2: remainder(BigDecimal.ZERO) did not throw an ArithmeticException for " + 1888 type.getName()); 1889 } catch (ArithmeticException e) { 1890 // OK, ignore 1891 } catch (Exception e) { 1892 AssertJUnit.fail("Section 4.2.2: remainder(BigDecimal.ZERO) did not throw an ArithmeticException for " + 1893 type.getName() + 1894 ", but " + e); 1895 } 1896 } 1897 } 1898 1899 /** 1900 * Test remainder(null) must throw a NullPointerException 1901 */ 1902 @SpecAssertion(section = "4.2.2", id = "422-D21") 1903 @Test(description = "4.2.2 For each amount class, ensure remainder(null), throws NullPointerException.") 1904 public void testRemainderNull() { 1905 for (Class type : MonetaryAmounts.getAmountTypes()) { 1906 if (type.equals(TestAmount.class)) { 1907 continue; 1908 } 1909 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1910 try { 1911 MonetaryAmount mActualResult = mAmount1.remainder(null); 1912 AssertJUnit.fail("Section 4.2.2: NullPointerException expected for remainder with null, type was " + 1913 type.getName()); 1914 } catch (NullPointerException e) { 1915 // expected 1916 } 1917 } 1918 } 1919 1920 /** 1921 * Test remainder(null) must throw a NullPointerException 1922 */ 1923 @SpecAssertion(section = "4.2.2", id = "422-D21") 1924 @Test(description = "4.2.2 For each amount class, ensure remainder(Double.NaN), throws ArithmeticException.") 1925 public void testRemainder_DoubleNaN() { 1926 for (Class type : MonetaryAmounts.getAmountTypes()) { 1927 if (type.equals(TestAmount.class)) { 1928 continue; 1929 } 1930 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1931 try { 1932 MonetaryAmount mActualResult = mAmount1.remainder(Double.NaN); 1933 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected for remainder(Double.NaN), type was " + 1934 type.getName()); 1935 } catch (ArithmeticException e) { 1936 // expected 1937 } 1938 } 1939 } 1940 1941 /** 1942 * Test remainder(null) must throw a NullPointerException 1943 */ 1944 @SpecAssertion(section = "4.2.2", id = "422-D21") 1945 @Test(description = "4.2.2 For each amount class, ensure remainder(Double.POSITIVE_INFINITY), throws ArithmeticException.") 1946 public void testRemainder_DoublePOSITIVE_INFINITY() { 1947 for (Class type : MonetaryAmounts.getAmountTypes()) { 1948 if (type.equals(TestAmount.class)) { 1949 continue; 1950 } 1951 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1952 MonetaryAmount mActualResult = mAmount1.remainder(Double.POSITIVE_INFINITY); 1953 AssertJUnit.assertEquals(getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(), mActualResult); 1954 } 1955 } 1956 1957 /** 1958 * Test remainder(null) must throw a NullPointerException 1959 */ 1960 @SpecAssertion(section = "4.2.2", id = "422-D21") 1961 @Test(description = "4.2.2 For each amount class, ensure remainder(Double.NEGATIVE_INFINITY), throws ArithmeticException.") 1962 public void testRemainder_DoubleNEGATIVE_INFINITY() { 1963 for (Class type : MonetaryAmounts.getAmountTypes()) { 1964 if (type.equals(TestAmount.class)) { 1965 continue; 1966 } 1967 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 1968 MonetaryAmount mActualResult = mAmount1.remainder(Double.NEGATIVE_INFINITY); 1969 AssertJUnit.assertEquals(getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(), mActualResult); 1970 } 1971 } 1972 1973 1974 /** 1975 * Test divideAndRemainder()allow to divide/remind numbers. 1976 */ 1977 @SpecAssertion(section = "4.2.2", id = "422-D22") 1978 @Test(description = "4.2.2 For each amount class, ensure correct divideAndRemainder().") 1979 public void testDivideAndRemainder() { 1980 for (Class type : MonetaryAmounts.getAmountTypes()) { 1981 if (type.equals(TestAmount.class)) { 1982 continue; 1983 } 1984 MonetaryAmountFactory<?> f = getAmountFactory(type); 1985 MonetaryAmount money1 = f.setNumber(BigDecimal.ONE).setCurrency("EUR").create(); 1986 if (f.getDefaultMonetaryContext().getMaxScale() < 5) { 1987 MonetaryAmount[] divideAndRemainder = money1.divideAndRemainder(new BigDecimal("0.6")); 1988 AssertJUnit.assertEquals("Section 4.2.2: divideAndRemainder(0.6)[0] failed for " + type.getName(), 1989 divideAndRemainder[0].getNumber().numberValue(BigDecimal.class) 1990 .stripTrailingZeros(), BigDecimal.ONE.stripTrailingZeros()); 1991 AssertJUnit.assertEquals("Section 4.2.2: divideAndRemainder(0.6)[1] failed for " + type.getName(), 1992 divideAndRemainder[1].getNumber().numberValue(BigDecimal.class) 1993 .stripTrailingZeros(), new BigDecimal("0.4").stripTrailingZeros()); 1994 } else { 1995 MonetaryAmount[] divideAndRemainder = money1.divideAndRemainder(new BigDecimal("0.50001")); 1996 AssertJUnit.assertEquals("Section 4.2.2: divideAndRemainder(0.50001)[0] failed for " + type.getName(), 1997 divideAndRemainder[0].getNumber().numberValue(BigDecimal.class) 1998 .stripTrailingZeros(), BigDecimal.ONE.stripTrailingZeros()); 1999 AssertJUnit.assertEquals("Section 4.2.2: divideAndRemainder(0.50001)[1] failed for " + type.getName(), 2000 divideAndRemainder[1].getNumber().numberValue(BigDecimal.class) 2001 .stripTrailingZeros(), new BigDecimal("0.49999").stripTrailingZeros()); 2002 } 2003 } 2004 } 2005 2006 /** 2007 * Test divideAndRemainder(0) throws an ArithmeticException. 2008 */ 2009 @SpecAssertion(section = "4.2.2", id = "422-D23") 2010 @Test(description = "4.2.2 For each amount class, ensure correct divideAndRemainderZero().") 2011 public void testDivideAndRemainderZero() { 2012 for (Class type : MonetaryAmounts.getAmountTypes()) { 2013 if (type.equals(TestAmount.class)) { 2014 continue; 2015 } 2016 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 2017 try { 2018 mAmount1.divideAndRemainder(BigDecimal.ZERO); 2019 AssertJUnit.fail("Section 4.2.2: divideAndRemainder(0) for " + type.getName() + 2020 ", should throw ArithmeticException!"); 2021 } catch (ArithmeticException e) { 2022 // expected 2023 } catch (Exception e) { 2024 AssertJUnit.fail("Section 4.2.2: Unexpected exception for divideAndRemainder(0) for " + type.getName() + 2025 ", should be ArithmeticException, but was " + e); 2026 } 2027 } 2028 } 2029 2030 /** 2031 * Test divideAndRemainder(null) throws an NullPointerException. 2032 */ 2033 @SpecAssertion(section = "4.2.2", id = "422-D24") 2034 @Test(description = "4.2.2 For each amount class, ensure divideAndRemainder(null) throws a NullPointerException.") 2035 public void testDivideAndRemainderNull() { 2036 for (Class type : MonetaryAmounts.getAmountTypes()) { 2037 if (type.equals(TestAmount.class)) { 2038 continue; 2039 } 2040 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 2041 try { 2042 MonetaryAmount[] mActualResult = mAmount1.divideAndRemainder(null); 2043 AssertJUnit.fail("Section 4.2.2: NullPointerException expected for divideAndRemainder with null, " + 2044 "type was " + 2045 type.getName()); 2046 } catch (NullPointerException e) { 2047 // expected 2048 } 2049 } 2050 } 2051 2052 /** 2053 * Test divideAndRemainder(null) throws an NullPointerException. 2054 */ 2055 @SpecAssertion(section = "4.2.2", id = "422-D24") 2056 @Test(description = "4.2.2 For each amount class, ensure divideAndRemainder(Double.NaN) throws a ArithmeticException.") 2057 public void testDivideAndRemainderDoubleNaN() { 2058 for (Class type : MonetaryAmounts.getAmountTypes()) { 2059 if (type.equals(TestAmount.class)) { 2060 continue; 2061 } 2062 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 2063 try { 2064 MonetaryAmount[] mActualResult = mAmount1.divideAndRemainder(Double.NaN); 2065 AssertJUnit.fail("Section 4.2.2: ArithmeticException expected for divideAndRemainder with Double.NaN, " + 2066 "type was " + 2067 type.getName()); 2068 } catch (ArithmeticException e) { 2069 // expected 2070 } 2071 } 2072 } 2073 2074 /** 2075 * Test divideAndRemainder(null) throws an NullPointerException. 2076 */ 2077 @SpecAssertion(section = "4.2.2", id = "422-D24") 2078 @Test(description = "4.2.2 For each amount class, ensure divideAndRemainder(Double.POSITIVE_INFINITY) returns ZERO amount.") 2079 public void testDivideAndRemainderDoublePOSITIVE_INFINITY() { 2080 for (Class type : MonetaryAmounts.getAmountTypes()) { 2081 if (type.equals(TestAmount.class)) { 2082 continue; 2083 } 2084 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 2085 MonetaryAmount[] mActualResult = mAmount1.divideAndRemainder(Double.POSITIVE_INFINITY); 2086 MonetaryAmount zero = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 2087 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected for divideAndRemainder with Double.POSITIVE_INFINITY, " + 2088 "type was " + 2089 type.getName(), zero, 2090 mActualResult[0]); 2091 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected for divideAndRemainder with Double.POSITIVE_INFINITY, " + 2092 "type was " + 2093 type.getName(), zero, 2094 mActualResult[1]); 2095 } 2096 } 2097 2098 /** 2099 * Test divideAndRemainder(null) throws an NullPointerException. 2100 */ 2101 @SpecAssertion(section = "4.2.2", id = "422-D24") 2102 @Test(description = "4.2.2 For each amount class, ensure divideAndRemainder(Double.NEGATIVE_INFINITY) returns ZERO amount.") 2103 public void testDivideAndRemainderDoubleNEGATIVE_INFINITY() { 2104 for (Class type : MonetaryAmounts.getAmountTypes()) { 2105 if (type.equals(TestAmount.class)) { 2106 continue; 2107 } 2108 MonetaryAmount mAmount1 = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(10).create(); 2109 MonetaryAmount[] mActualResult = mAmount1.divideAndRemainder(Double.NEGATIVE_INFINITY); 2110 MonetaryAmount zero = getAmountFactory(type).setCurrency(DEFAULT_CURRENCY).setNumber(0).create(); 2111 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected for divideAndRemainder with Double.NEGATIVE_INFINITY, " + 2112 "type was " + 2113 type.getName(), zero, 2114 mActualResult[0]); 2115 AssertJUnit.assertEquals("Section 4.2.2: ZERO amount expected for divideAndRemainder with Double.NEGATIVE_INFINITY, " + 2116 "type was " + 2117 type.getName(), zero, 2118 mActualResult[1]); 2119 } 2120 } 2121 2122 2123 /** 2124 * Test divideAndRemainder(1) returns this/ZERO. 2125 */ 2126 @SpecAssertion(section = "4.2.2", id = "422-D25") 2127 @Test(description = "4.2.2 For each amount class, ensure divideAndRemainder(1) returns same instance.") 2128 public void testDivideAndRemainderOne() { 2129 for (Class type : MonetaryAmounts.getAmountTypes()) { 2130 if (type.equals(TestAmount.class)) { 2131 continue; 2132 } 2133 MonetaryAmountFactory<?> f = getAmountFactory(type); 2134 MonetaryAmount m = f.setNumber(100).setCurrency("CHF").create(); 2135 AssertJUnit.assertEquals( 2136 "Section 4.2.2: DivideAndRemainder not returning correct result for type: " + type.getName(), 2137 BigDecimal.valueOf(33), 2138 m.divideAndRemainder(3)[0].getNumber().numberValue(BigDecimal.class).stripTrailingZeros()); 2139 AssertJUnit.assertEquals( 2140 "Section 4.2.2: DivideAndRemainder not returning correct result for type: " + type.getName(), 2141 BigDecimal.valueOf(1), 2142 m.divideAndRemainder(3)[1].getNumber().numberValue(BigDecimal.class).stripTrailingZeros()); 2143 AssertJUnit.assertEquals( 2144 "Section 4.2.2: DivideAndRemainder not returning correct result for type: " + type.getName(), 2145 BigDecimal.ONE, 2146 m.divideAndRemainder(BigDecimal.valueOf(3))[1].getNumber().numberValue(BigDecimal.class) 2147 .stripTrailingZeros()); 2148 } 2149 } 2150 2151 /** 2152 * Test scaleByPowerOfTen()allow to scale by power of 10. 2153 */ 2154 @SpecAssertion(section = "4.2.2", id = "422-D26") 2155 @Test(description = "4.2.2 For each amount class, ensure scaleByPowerOfTen(1) returns correct results.") 2156 public void testScaleByPowerOfTen() { 2157 for (Class type : MonetaryAmounts.getAmountTypes()) { 2158 if (type.equals(TestAmount.class)) { 2159 continue; 2160 } 2161 MonetaryAmountFactory<?> f = getAmountFactory(type); 2162 f.setCurrency("CHF"); 2163 MonetaryAmount[] amounts = new MonetaryAmount[]{f.setNumber(100).create(), f.setNumber(342444).create(), 2164 f.setNumber(2312213.435).create(), f.setNumber(BigDecimal.ZERO).create(), 2165 f.setNumber(-100).create(), f.setNumber(-723527.3653).create()}; 2166 2167 for (MonetaryAmount m : amounts) { 2168 for (int p = -3; p < 3; p++) { 2169 BigDecimal bdExpected = m.scaleByPowerOfTen(p).getNumber().numberValue(BigDecimal.class); 2170 BigDecimal bdCalculated = m.getNumber().numberValue(BigDecimal.class).scaleByPowerOfTen(p); 2171 bdCalculated = bdCalculated.setScale(m.getContext().getMaxScale(), RoundingMode.HALF_EVEN); 2172 if (bdExpected.signum() == 0) { 2173 AssertJUnit.assertTrue("Section 4.2.2: Invalid " + m + " -> scaleByPowerOfTen(" + p + ") for " + 2174 type.getName(), bdCalculated.signum() == 0); 2175 } else { 2176 AssertJUnit 2177 .assertEquals("Section 4.2.2: Invalid " + m + " -> scaleByPowerOfTen(" + p + ") for " + 2178 type.getName(), bdExpected 2179 .setScale(m.getContext().getMaxScale() - 1, 2180 RoundingMode.HALF_EVEN).stripTrailingZeros(), 2181 bdCalculated.setScale(m.getContext().getMaxScale() - 1, 2182 RoundingMode.HALF_EVEN).stripTrailingZeros()); 2183 } 2184 } 2185 } 2186 } 2187 } 2188 2189 /** 2190 * Test abs() for getting the absolute value. 2191 */ 2192 @SpecAssertion(section = "4.2.2", id = "422-D27") 2193 @Test(description = "4.2.2 For each amount class, test absolute().") 2194 public void testAbsolute() { 2195 for (Class type : MonetaryAmounts.getAmountTypes()) { 2196 if (type.equals(TestAmount.class)) { 2197 continue; 2198 } 2199 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 2200 f.setCurrency("CHF"); 2201 MonetaryAmount m = f.setNumber(10).create(); 2202 AssertJUnit 2203 .assertEquals("Section 4.2.2: abs(m) !equals m, if m > 0 for type: " + type.getName(), m, m.abs()); 2204 AssertJUnit.assertTrue("Section 4.2.2: abs(m) != m, if m > 0 for type: " + type.getName(), m == m.abs()); 2205 m = f.setNumber(0).create(); 2206 AssertJUnit 2207 .assertEquals("Section 4.2.2: abs(m) != equals, if m == 0 for type: " + type.getName(), m, m.abs()); 2208 AssertJUnit.assertTrue("Section 4.2.2: abs(m) != m, if m == 0 for type: " + type.getName(), m == m.abs()); 2209 m = f.setNumber(-10).create(); 2210 AssertJUnit.assertEquals("Section 4.2.2: abs(m) == m, if m < 0 for type: " + type.getName(), m.negate(), 2211 m.abs()); 2212 AssertJUnit.assertTrue("Section 4.2.2: abs(m) == m, if m < 0 for type: " + type.getName(), m != m.abs()); 2213 } 2214 } 2215 2216 /** 2217 * Test negate() for negating a value. 2218 */ 2219 @SpecAssertion(section = "4.2.2", id = "422-D28") 2220 @Test(description = "4.2.2 For each amount class, test negate().") 2221 public void testNegate() { 2222 for (Class type : MonetaryAmounts.getAmountTypes()) { 2223 if (type.equals(TestAmount.class)) { 2224 continue; 2225 } 2226 MonetaryAmountFactory<MonetaryAmount> f = getAmountFactory(type); 2227 f.setCurrency("CHF"); 2228 MonetaryAmount m = f.setNumber(100).create(); 2229 AssertJUnit 2230 .assertEquals("Section 4.2.2: negate(-x) failed for " + type.getName(), f.setNumber(-100).create(), 2231 m.negate()); 2232 m = f.setNumber(-123.234).create(); 2233 AssertJUnit.assertEquals("Section 4.2.2: negate(+x) failed for " + type.getName(), 2234 f.setNumber(123.234).create(), m.negate()); 2235 } 2236 } 2237 2238 /** 2239 * Ensure with(MonetaryOperator) can be called and produces 2240 * amounts of the same type and correct value. 2241 */ 2242 @SpecAssertion(section = "4.2.2", id = "422-E1") 2243 @Test(description = "4.2.2 For each amount class, test with().") 2244 public void testWith() { 2245 MonetaryOperator op = (amount) -> amount; 2246 for (Class type : MonetaryAmounts.getAmountTypes()) { 2247 if (type.equals(TestAmount.class)) { 2248 continue; 2249 } 2250 MonetaryAmount amount = getAmountFactory(type).setCurrency("CHF").setNumber(10).create(); 2251 MonetaryAmount amount2 = amount.with(op); 2252 AssertJUnit.assertTrue( 2253 "Section 4.2.2: MonetaryAmount returned from operator is wrapped by implementation of type: " + 2254 type.getName(), amount == amount2); 2255 final MonetaryAmount result = getAmountFactory(type).setCurrency("CHF").setNumber(4).create(); 2256 MonetaryOperator op2 = (m) -> result; 2257 amount2 = amount.with(op); 2258 AssertJUnit.assertTrue( 2259 "Section 4.2.2: MonetaryAmount returned from operator is wrapped by implementation of type: " + 2260 type.getName(), amount == amount2); 2261 } 2262 } 2263 2264 /** 2265 * Ensure with(MonetaryOperator) can be called and produces 2266 * amounts of the same type and correct value, testing operators provided by TCKTestSetup. 2267 */ 2268 @SpecAssertion(section = "4.2.2", id = "422-E1") 2269 @Test(description = "4.2.2 For each amount class, test with().") 2270 public void testWith4ProvidedOperators() { 2271 for (MonetaryOperator op : TCKTestSetup.getTestConfiguration().getMonetaryOperators4Test()) { 2272 for (Class type : MonetaryAmounts.getAmountTypes()) { 2273 if (type.equals(TestAmount.class)) { 2274 continue; 2275 } 2276 MonetaryAmount amount = getAmountFactory(type).setCurrency("CHF").setNumber(10).create(); 2277 MonetaryAmount amount2 = amount.with(op); 2278 AssertJUnit.assertTrue( 2279 "Section 4.2.2: MonetaryAmount returned from operator is wrapped by implementation of type: " + 2280 type.getName(), amount.getClass() == amount2.getClass()); 2281 final MonetaryAmount result = getAmountFactory(type).setCurrency("CHF").setNumber(4).create(); 2282 MonetaryOperator op2 = (m) -> m; 2283 amount2 = amount.with(op2); 2284 AssertJUnit.assertTrue( 2285 "Section 4.2.2: MonetaryAmount returned from operator is wrapped by implementation of type: " + 2286 type.getName(), amount == amount2); 2287 } 2288 } 2289 } 2290 2291 /** 2292 * Test with(m) throws a MonetaryException, if m throws any exception. 2293 */ 2294 @SpecAssertion(section = "4.2.2", id = "422-E2") 2295 @Test(description = "4.2.2 Bad case: For each amount class, test with(), operator throws exception.") 2296 public void testWithInvalidOperator() { 2297 MonetaryOperator op = new MonetaryOperator() { 2298 @Override 2299 public MonetaryAmount apply(MonetaryAmount value) { 2300 throw new IllegalStateException(); 2301 } 2302 }; 2303 for (Class type : MonetaryAmounts.getAmountTypes()) { 2304 if (type.equals(TestAmount.class)) { 2305 continue; 2306 } 2307 MonetaryAmountFactory factory = getAmountFactory(type); 2308 MonetaryAmount amount = factory.setCurrency("XXX").setNumber(1).create(); 2309 try { 2310 amount.with(op); 2311 AssertJUnit.fail("Section 4.2.2: MonetaryException expected as operator fails, type was " + 2312 type.getName()); 2313 } catch (MonetaryException e) { 2314 // OK, everything else makes the test fail! 2315 } 2316 } 2317 } 2318 2319 /** 2320 * Test with(null) throws a NullPointerException. 2321 */ 2322 @SpecAssertion(section = "4.2.2", id = "422-E2") 2323 @Test(description = "4.2.2 Bad case: For each amount class, test with(null), expected NullPointerException.") 2324 public void testWithNull() { 2325 for (Class type : MonetaryAmounts.getAmountTypes()) { 2326 if (type.equals(TestAmount.class)) { 2327 continue; 2328 } 2329 MonetaryAmountFactory factory = getAmountFactory(type); 2330 MonetaryAmount amount = factory.setCurrency("XXX").setNumber(1).create(); 2331 try { 2332 amount.with(null); 2333 AssertJUnit.fail("Section 4.2.2: NullPointerException expected as operator applied is null, type was " + 2334 type.getName()); 2335 } catch (NullPointerException e) { 2336 // OK, everything else makes the test fail! 2337 } 2338 } 2339 } 2340 2341 /** 2342 * Test with(null) throws a NullPointerException. 2343 */ 2344 @SpecAssertion(section = "4.2.2", id = "422-E2") 2345 @Test(description = "4.2.2 Bad case: For each amount class, test with(), operator throws exception.") 2346 public void testWithNull4ProvidedOperators() { 2347 for (MonetaryOperator op : TCKTestSetup.getTestConfiguration().getMonetaryOperators4Test()) { 2348 try { 2349 op.apply(null); 2350 AssertJUnit.fail("Section 4.2.2: NullPointerException expected as operator was applied on null, " + 2351 "operator was " + 2352 op.getClass().getName()); 2353 } catch (NullPointerException e) { 2354 // OK, everything else makes the test fail! 2355 } 2356 } 2357 } 2358 2359 /** 2360 * Ensure query(MonetaryQUery) can be called and produces 2361 * valuable results. 2362 */ 2363 @SpecAssertion(section = "4.2.2", id = "422-E3") 2364 @Test(description = "4.2.2 For each amount class, test query().") 2365 public void testQuery() { 2366 MonetaryQuery<Integer> query = new MonetaryQuery<Integer>() { 2367 @Override 2368 public Integer queryFrom(MonetaryAmount amount) { 2369 return amount.getNumber().intValue(); 2370 } 2371 }; 2372 for (Class type : MonetaryAmounts.getAmountTypes()) { 2373 if (type.equals(TestAmount.class)) { 2374 continue; 2375 } 2376 MonetaryAmount amount = getAmountFactory(type).setCurrency("CHF").setNumber(10).create(); 2377 Integer value = amount.query(query); 2378 AssertJUnit.assertTrue( 2379 "Section 4.2.2: Value returned from MonetaryAmount Query is not correct for " + type.getName(), 2380 value == 10); 2381 amount = getAmountFactory(type).setCurrency("CHF").setNumber(4.5).create(); 2382 value = amount.query(query); 2383 AssertJUnit.assertTrue( 2384 "Section 4.2.2: Value returned from MonetaryAmount Query is not correct for " + type.getName(), 2385 value == 4); 2386 } 2387 } 2388 2389 /** 2390 * Test query(q) throws a MonetaryException, if q throws any exception. 2391 */ 2392 @SpecAssertion(section = "4.2.2", id = "422-E4") 2393 @Test(description = "4.2.2 For each amount class, test query(), MonetaryQuery throws exception, " + 2394 "MonetaryException expected.") 2395 public void testQueryInvalidQuery() { 2396 MonetaryQuery<Integer> query = new MonetaryQuery<Integer>() { 2397 @Override 2398 public Integer queryFrom(MonetaryAmount amount) { 2399 throw new IllegalStateException(); 2400 } 2401 }; 2402 for (Class type : MonetaryAmounts.getAmountTypes()) { 2403 if (type.equals(TestAmount.class)) { 2404 continue; 2405 } 2406 TestUtils.testComparable("Section 4.2.2", type); 2407 MonetaryAmountFactory factory = getAmountFactory(type); 2408 MonetaryAmount amount = factory.setCurrency("XXX").setNumber(1).create(); 2409 try { 2410 amount.query(query); 2411 AssertJUnit.fail("Section 4.2.2: MonetaryException expected as query applied is failing, type was " + 2412 type.getName()); 2413 } catch (MonetaryException e) { 2414 // OK, everything else makes the test fail! 2415 } 2416 } 2417 } 2418 2419 /** 2420 * Test query(null) throws a NullPointerException. 2421 */ 2422 @SpecAssertion(section = "4.2.2", id = "422-E4") 2423 @Test(description = "4.2.2 For each amount class, test query(null), NullPointerException expected.") 2424 public void testQueryNull() { 2425 for (Class type : MonetaryAmounts.getAmountTypes()) { 2426 if (type.equals(TestAmount.class)) { 2427 continue; 2428 } 2429 TestUtils.testComparable("Section 4.2.2", type); 2430 MonetaryAmountFactory factory = getAmountFactory(type); 2431 MonetaryAmount amount = factory.setCurrency("XXX").setNumber(1).create(); 2432 try { 2433 amount.query(null); 2434 AssertJUnit.fail("Section 4.2.2: NullPointerException expected as query applied is null, type was " + 2435 type.getName()); 2436 } catch (NullPointerException e) { 2437 // OK, everything else makes the test fail! 2438 } 2439 } 2440 } 2441 2442 /** 2443 * Implementations of MonetaryAmount must implement hashCode, 2444 * considering number, currency and implementation type, 2445 * monetary 2446 * context. 2447 */ 2448 @SpecAssertion(section = "4.2.2", id = "422-F1") 2449 @Test(description = "4.2.2 For each amount class, test implements hashCode().") 2450 public void testImplementsHashCode() { 2451 for (Class type : MonetaryAmounts.getAmountTypes()) { 2452 if (type.equals(TestAmount.class)) { 2453 continue; 2454 } 2455 MonetaryAmount amount = getAmountFactory(type).setCurrency("USD").setNumber(0).create(); 2456 TestUtils.testHasPublicMethod("Section 4.2.2", type, type, "hashCode"); 2457 MonetaryAmount amount2 = getAmountFactory(type).setCurrency("USD").setNumber(0).create(); 2458 AssertJUnit.assertEquals("Section 4.2.2: hashCode() for equal amounts differ for type " + type.getName(), 2459 amount.hashCode(), amount2.hashCode()); 2460 } 2461 } 2462 2463 /** 2464 * Implementations of MonetaryAmount must implement 2465 * equals, 2466 * considering number, currency and implementation type, 2467 * monetary 2468 * context. 2469 */ 2470 @SpecAssertion(section = "4.2.2", id = "422-F2") 2471 @Test(description = "4.2.2 For each amount class, test implements equals().") 2472 public void testImplementsEquals() { 2473 for (Class type : MonetaryAmounts.getAmountTypes()) { 2474 if (type.equals(TestAmount.class)) { 2475 continue; 2476 } 2477 MonetaryAmount amount = getAmountFactory(type).setCurrency("XXX").setNumber(0).create(); 2478 TestUtils.testHasPublicMethod("Section 4.2.2", type, type, "equals", Object.class); 2479 MonetaryAmount amount2 = getAmountFactory(type).setCurrency("XXX").setNumber(0).create(); 2480 AssertJUnit 2481 .assertEquals("Section 4.2.2: equals(Object) for equal amounts returns false for " + type.getName(), 2482 amount, amount2); 2483 } 2484 } 2485 2486 /** 2487 * Implementations of MonetaryAmount must be Comparable. 2488 */ 2489 @SpecAssertion(section = "4.2.2", id = "422-F3") 2490 @Test(description = "4.2.2 For each amount class, test is Comparable.") 2491 public void testImplementComparable() { 2492 for (Class type : MonetaryAmounts.getAmountTypes()) { 2493 if (type.equals(TestAmount.class)) { 2494 continue; 2495 } 2496 TestUtils.testComparable("Section 4.2.2", type); 2497 MonetaryAmountFactory factory = getAmountFactory(type); 2498 MonetaryAmount amount = factory.setCurrency("XXX").setNumber(0).create(); 2499 MonetaryAmount amount2 = factory.setCurrency("XXX").setNumber(0).create(); 2500 MonetaryAmount amount3 = factory.setCurrency("CHF").setNumber(1).create(); 2501 MonetaryAmount amount4 = factory.setCurrency("XXX").setNumber(1).create(); 2502 2503 AssertJUnit.assertTrue("Section 4.2.2: Comparable failed for: " + type.getName(), 2504 ((Comparable) amount).compareTo(amount3) > 0); 2505 2506 AssertJUnit.assertTrue("Section 4.2.2: Comparable failed for: " + type.getName(), 2507 ((Comparable) amount3).compareTo(amount) < 0); 2508 2509 AssertJUnit.assertTrue("Section 4.2.2: Comparable failed for: " + type.getName(), 2510 ((Comparable) amount).compareTo(amount4) < 0); 2511 2512 AssertJUnit.assertTrue("Section 4.2.2: Comparable failed for: " + type.getName(), 2513 ((Comparable) amount4).compareTo(amount) > 0); 2514 } 2515 } 2516 2517 /** 2518 * Implementations of MonetaryAmount must be Serializable. 2519 */ 2520 @SpecAssertion(section = "4.2.2", id = "422-F4") 2521 @Test(description = "4.2.2 For each amount class, test iis immutable.") 2522 public void testImmutable() { 2523 for (Class type : TCKTestSetup.getTestConfiguration().getAmountClasses()) { 2524 if (type.equals(TestAmount.class)) { 2525 continue; 2526 } 2527 TestUtils.testImmutable("Section 4.2.2", type); 2528 } 2529 for (Class type : MonetaryAmounts.getAmountTypes()) { 2530 if (type.equals(TestAmount.class)) { 2531 continue; 2532 } 2533 try { 2534 TestUtils.testImmutable("Section 4.2.2", type); 2535 } catch (MutabilityAssertionError e) { 2536 System.out 2537 .println("Warning: found non immutable MonetaryAmountType: " + type.getName() + ", details: " + 2538 e.getMessage()); 2539 } 2540 } 2541 } 2542 2543 2544}