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.format; 011 012import org.javamoney.tck.tests.internal.TestAmount; 013import org.javamoney.tck.tests.internal.TestMonetaryAmountBuilder; 014import org.jboss.test.audit.annotations.SpecAssertion; 015import org.jboss.test.audit.annotations.SpecVersion; 016import org.testng.AssertJUnit; 017import org.testng.annotations.Test; 018 019import javax.money.CurrencyUnit; 020import javax.money.MonetaryAmount; 021import javax.money.MonetaryAmountFactory; 022import javax.money.Monetary; 023import javax.money.MonetaryException; 024import javax.money.format.AmountFormatQuery; 025import javax.money.format.AmountFormatQueryBuilder; 026import javax.money.format.MonetaryAmountFormat; 027import javax.money.format.MonetaryFormats; 028import java.text.DecimalFormat; 029import java.util.HashSet; 030import java.util.Locale; 031import java.util.Set; 032 033import static org.testng.Assert.*; 034import static org.testng.AssertJUnit.fail; 035 036@SpecVersion(spec = "JSR 354", version = "1.0.0") 037public class FormattingMonetaryAmountsTest { 038 039 /** 040 * Format several amounts, created using the default factory, 041 * but 042 * also a test instance, provided by the TCK, to ensure no 043 * implementation 044 * dependencies on the implementation. 045 */ 046 @SpecAssertion(section = "4.4.1", id = "441-A1") 047 @Test(description = "4.4.1 Ensures the system.s default locale is supported for MonetaryAmountFormat.") 048 public void testNoDepOnAmountImplementation() { 049 final Locale defaultLocale = Locale.getDefault(); 050 MonetaryAmountFormat amountFormat = MonetaryFormats.getAmountFormat(defaultLocale); 051 final Number[] values = new Number[]{100, 10000000000000L}; 052 053 for (CurrencyUnit currency : Monetary.getCurrencies()) { 054 for (Number value : values) { 055 MonetaryAmount amount = 056 Monetary.getDefaultAmountFactory().setCurrency(currency.getCurrencyCode()) 057 .setNumber(value).create(); 058 String formattedAmount = amountFormat.format(amount); 059 MonetaryAmount amountMock = TestMonetaryAmountBuilder.getAmount(value, currency); 060 String formattedAmountMock = amountFormat.format(amountMock); 061 AssertJUnit.assertNotNull(formattedAmountMock); 062 assertEquals(formattedAmountMock, formattedAmount); 063 } 064 } 065 } 066 067 /** 068 * Print several amounts, created using the default factory, but 069 * also a test instance, provided by the TCK, to ensure no 070 * implementation 071 * dependencies on the implementation. 072 */ 073 @SpecAssertion(section = "4.4.1", id = "441-A2") 074 @Test(description = "4.4.1 Formats amounts using all available locales.") 075 public void testFormattingIsIndependentOfImplementation() { 076 for (Locale locale : MonetaryFormats.getAvailableLocales()) { 077 MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(locale); 078 Set<String> formatsProcuced = new HashSet<>(); 079 for (MonetaryAmountFactory fact : Monetary.getAmountFactories()) { 080 if (fact.getAmountType().equals(TestAmount.class)) { 081 continue; 082 } 083 MonetaryAmount amt = fact.setCurrency("USD").setNumber(10.5).create(); 084 String formatProduced = format.format(amt); 085 assertNotNull(formatProduced, "No MonetaryAmountFormat returned from MonetaryFormats." + 086 "getMonetaryFormat(Locale,String...) with supported Locale: " + locale); 087 assertFalse(formatProduced.isEmpty(), "MonetaryAmountFormat returned empty String for " + amt); 088 formatsProcuced.add(formatProduced); 089 } 090 assertFalse(formatsProcuced.isEmpty(), "No formatted amount available. Are there no amount?"); 091 assertFalse(formatsProcuced.size() > 1, 092 "Formatter produces different output for different amount classes(+" + 093 format.getClass() + "): " + formatsProcuced); 094 } 095 } 096 097 /** 098 * Parse back several amounts, input created using the 099 * formatting 100 * from 'Format_formatAmounts'. 101 */ 102 @SpecAssertion(section = "4.4.1", id = "441-A3") 103 @Test(description = "4.4.1 Test formats and parses (round-trip) any supported amount type for each supported " + 104 "Locale.") 105 public void testParseIsIndependentOfImplementation() { 106 for (Locale locale : MonetaryFormats.getAvailableLocales()) { 107 MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(locale); 108 for (MonetaryAmountFactory fact : Monetary.getAmountFactories()) { 109 if (fact.getAmountType().equals(TestAmount.class)) { 110 continue; 111 } 112 MonetaryAmount amt = fact.setCurrency("USD").setNumber(10.5).create(); 113 String formatProduced = format.format(amt); 114 assertNotNull(formatProduced, "No MonetaryAmountFormat returned from MonetaryFormats." + 115 "getMonetaryFormat(Locale,String...) with supported Locale: " + locale); 116 assertFalse(formatProduced.isEmpty(), "MonetaryAmountFormat returned empty String for " + amt); 117 try { 118 MonetaryAmount amtParsed = format.parse(formatProduced); 119 assertNotNull(amtParsed, "Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 120 "' using MonetaryAmountFormat: " + format); 121 } catch (MonetaryException e) { 122 fail("Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 123 "' using MonetaryAmountFormat: " + format.getClass().getName() + " for Locale: " + locale); 124 } 125 } 126 } 127 } 128 129 /** 130 * Get/set different amount styles (especially patterns, group 131 * sizes, group characters) and compare results with results as from 132 * RI. 133 * Also apply patterns without currency invovled. 134 */ 135 @SpecAssertion(section = "4.4.2", id = "442-A1") 136 @Test(description = 137 "4.4.2 Test formats and parses (round-trip) any supported amount type for each supported Locale, " + 138 "using different format queries.") 139 public void testParseDifferentStyles() { 140 for (Locale locale : MonetaryFormats.getAvailableLocales()) { 141 for (Class clazz : Monetary.getAmountTypes()) { 142 if (clazz.equals(TestAmount.class)) { 143 continue; 144 } 145 MonetaryAmountFactory fact = Monetary.getAmountFactory(clazz); 146 AmountFormatQuery query = AmountFormatQueryBuilder.of(locale).setMonetaryAmountFactory(fact).build(); 147 if (fact.getAmountType().equals(TestAmount.class)) { 148 continue; 149 } 150 MonetaryAmount amt = fact.setCurrency("USD").setNumber(10.5).create(); 151 MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(query); 152 String formatProduced = format.format(amt); 153 assertNotNull(formatProduced, "No MonetaryAmountFormat returned from MonetaryFormats." + 154 "getMonetaryFormat(Locale,String...) with supported Locale: " + locale); 155 assertFalse(formatProduced.isEmpty(), "MonetaryAmountFormat returned empty String for " + amt); 156 try { 157 MonetaryAmount amtParsed = format.parse(formatProduced); 158 assertNotNull(amtParsed, "Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 159 "' using MonetaryAmountFormat: " + format); 160 assertEquals(amtParsed.getClass(), clazz, 161 "Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 162 "' using MonetaryAmountFormat(invalid type " + 163 amtParsed.getClass().getName() + ") for format: " + format); 164 } catch (MonetaryException e) { 165 fail("Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 166 "' using MonetaryAmountFormat: " + format.getClass().getName() + " for Locale: " + locale); 167 } 168 } 169 } 170 } 171 172 173 /** 174 * Get/set default currency, try to parse patterns without 175 * currency information. 176 */ 177 @SpecAssertion(section = "4.4.1", id = "441-A4") 178 @Test(description = 179 "4.4.1 Test formats and parses (round-trip) any supported amount type for each supported Locale," + 180 " checks results for different currencies") 181 public void testParseWithDifferentCurrencies() { 182 for (Locale locale : MonetaryFormats.getAvailableLocales()) { 183 MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(locale); 184 for (MonetaryAmountFactory fact : Monetary.getAmountFactories()) { 185 if (fact.getAmountType().equals(TestAmount.class)) { 186 continue; 187 } 188 for (String currency : new String[]{"CHF", "USD", "GBP", "EUR"}) { 189 MonetaryAmount amt = fact.setCurrency(currency).setNumber(10.5).create(); 190 String formatProduced = format.format(amt); 191 assertNotNull(formatProduced, "No MonetaryAmountFormat returned from MonetaryFormats." + 192 "getMonetaryFormat(Locale,String...) with supported Locale: " + locale); 193 assertFalse(formatProduced.isEmpty(), "MonetaryAmountFormat returned empty String for " + amt); 194 try { 195 MonetaryAmount amtParsed = format.parse(formatProduced); 196 assertNotNull(amtParsed, "Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 197 "' using MonetaryAmountFormat: " + format); 198 assertEquals(amtParsed.getCurrency().getCurrencyCode(), currency, 199 "Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 200 "' using MonetaryAmountFormat(invalid currency " + 201 amtParsed.getCurrency().getCurrencyCode() + "): " + format); 202 } catch (MonetaryException e) { 203 fail("Reverse-parsing of MonetaryAmount failed for '" + formatProduced + 204 "' using MonetaryAmountFormat: " + format.getClass().getName() + " for Locale: " + locale); 205 } 206 } 207 } 208 } 209 } 210 211 212 /** 213 * AccessingMonetaryAmountFormat using 214 * MonetaryFormats.getAmountFormat(Locale locale), all locales 215 * available also from java.text.DecimalFormat must be supported. 216 */ 217 @SpecAssertion(section = "4.4.3", id = "443-A1") 218 @Test(description = "4.4.3 Ensures all Locales defined by DecimalFormat.getAvailableLocales() are available for " + 219 "monetary formatting.") 220 public void testLocalesSupported() { 221 Locale[] jdkDecimalFormatLocales = DecimalFormat.getAvailableLocales(); 222 for (Locale jdkDecimalFormatLocale : jdkDecimalFormatLocales) { 223 MonetaryAmountFormat amountFormat = MonetaryFormats.getAmountFormat(jdkDecimalFormatLocale); 224 AssertJUnit.assertNotNull(amountFormat); 225 assertEquals(jdkDecimalFormatLocale, amountFormat.getContext().getLocale()); 226 } 227 } 228 229 /** 230 * AccessingMonetaryAmountFormat using 231 * MonetaryFormats.getAmountFormat(AmountFormatContext style), all locales 232 * available also from java.text.DecimalFormat must be supported 233 * (using AmountFormatContext.of(Locale)). 234 */ 235 @Test(description = "4.4.3 Ensures for each locale defined by DecimalFormat.getAvailableLocales() a " + 236 "MonetaryAmountFormat instance is provided.") 237 @SpecAssertion(section = "4.4.3", id = "443-A2") 238 public void testGetAmountFormat() { 239 for (Locale locale : DecimalFormat.getAvailableLocales()) { 240 AssertJUnit.assertNotNull(MonetaryFormats.getAmountFormat(AmountFormatQuery.of(locale))); 241 } 242 } 243 244 /** 245 * Test MonetaryFormats.getAvailableLocales, all locales available also from java.text.DecimalFormat must be 246 * supported (using AmountFormatContext.of(Locale)), more locales are possible. 247 */ 248 @Test(description = "4.4.3 Ensures for each locale defined by DecimalFormat.getAvailableLocales() a " + 249 "MonetaryFormats.isAvailable(Locale) is true.") 250 @SpecAssertion(section = "4.4.3", id = "443-A3") 251 public void testGetAvailableLocales() { 252 Set<Locale> locales = MonetaryFormats.getAvailableLocales(); 253 for (Locale locale : DecimalFormat.getAvailableLocales()) { 254 if (Locale.ROOT.equals(locale)) { 255 continue; 256 } 257 AssertJUnit.assertTrue( 258 "MonetaryFormats.getAvailableLocales(); Locale supported by JDKs DecimalFormat is not available: " + 259 locale, locales.contains(locale)); 260 } 261 } 262 263 /** 264 * Test MonetaryFormats.getAvailableLocales, all locales available also from java.text.DecimalFormat must be 265 * supported (using AmountFormatContext.of(Locale)), more locales are possible. 266 */ 267 @Test(description = "4.4.3 Ensures for each locale defined by DecimalFormat.getAvailableLocales() a " + 268 "MonetaryFormats.getAmountFormat(AmountFormatQuery) returns a formatter.") 269 @SpecAssertion(section = "4.4.3", id = "443-A3") 270 public void testAmountStyleOf() { 271 for (Locale locale : DecimalFormat.getAvailableLocales()) { 272 AssertJUnit.assertNotNull(MonetaryFormats.getAmountFormat(AmountFormatQuery.of(locale))); 273 } 274 } 275}