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.conversion;
011
012import org.jboss.test.audit.annotations.SpecAssertion;
013import org.jboss.test.audit.annotations.SpecVersion;
014import org.testng.AssertJUnit;
015import org.testng.annotations.Test;
016
017import javax.money.Monetary;
018import javax.money.MonetaryException;
019import javax.money.convert.ConversionContext;
020import javax.money.convert.ConversionQuery;
021import javax.money.convert.ConversionQueryBuilder;
022import javax.money.convert.CurrencyConversion;
023import javax.money.convert.ExchangeRateProvider;
024import javax.money.convert.MonetaryConversions;
025import javax.money.convert.ProviderContext;
026
027/**
028 * Tests for MonetaryConversions.
029 */
030@SpecVersion(spec = "JSR 354", version = "1.0.0")
031public class MonetaryConversionsTest {
032
033    // ************************************* A. Test Basic MonetaryConversions Accessors *****************************
034
035    /**
036     * Ensure at least one conversion provider is available.<p>
037     * Hint: ignore all TCK test providers, only count up productive providers.
038     */
039    @Test(description = "4.3.1 Ensure at least one conversion provider is available, TestRateProvider must be present.")
040    @SpecAssertion(id = "431-A1", section = "4.3.1")
041    public void testProvidersAvailable() {
042        int providerCount = 0;
043        for (String providername : MonetaryConversions.getConversionProviderNames()) {
044            if (!"TestRateProvider".equals(providername)) {
045                providerCount++;
046            }
047        }
048        AssertJUnit.assertTrue("At least one conversion provider must be available/registered.", providerCount > 0);
049    }
050
051    /**
052     * Access and test different Currency Conversions for the provider in place.<p>
053     * Test TCK providers, but also test implementation providers. Doing the ladder it
054     * is not possible to test the rates quality, just that rates are returned if necessary.
055     */
056    @Test(description =
057            "4.3.1 Access Conversion to term currency code XXX for all providers that support according " +
058                    "conversion, if" +
059                    "available a non-null CurrencyConversion must be provided.")
060    @SpecAssertion(id = "431-A2", section = "4.3.1")
061    public void testConversionsAreAvailable() {
062        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
063            try {
064                if (MonetaryConversions.isConversionAvailable("XXX", providerName)) {
065                    CurrencyConversion conv = MonetaryConversions.getConversion("XXX", providerName);
066                    AssertJUnit.assertNotNull(
067                            "CurrencyConversion returned from MonetaryConversions.getConversion(String, " +
068                                    "String...) should never be null: " +
069                                    providerName, conv);
070                    AssertJUnit.assertTrue("CurrencyConversion is not flagged as available, " +
071                                    "though it was returned from MonetaryConversions.getConversion" +
072                                    "(String," +
073                                    " String...): " +
074                                    providerName,
075                            MonetaryConversions.isConversionAvailable("XXX", providerName));
076                }
077            } catch (MonetaryException e) {
078                AssertJUnit.assertFalse(
079                        "CurrencyConversion is not flagged as NOT available, though it is not accessible from " +
080                                "MonetaryConversions.getConversion(String, String...): " +
081                                providerName, MonetaryConversions.isConversionAvailable("XXX", providerName));
082            }
083        }
084    }
085
086    /**
087     * Access and test different Currency Conversions for the provider in place.<p>
088     * Test TCK providers, but also test implementation providers. Doing the ladder it
089     * is not possible to test the rates quality, just that rates are returned if necessary.
090     */
091    @Test(description =
092            "4.3.1 Access Conversion by query to term currency XXX for all providers that support according " +
093                    "conversion, if" +
094                    "available a non-null CurrencyConversion must be provided.")
095    @SpecAssertion(id = "431-A2", section = "4.3.1")
096    public void testConversionsAreAvailableWithQuery() {
097        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
098            ConversionQuery query =
099                    ConversionQueryBuilder.of().setTermCurrency("XXX").setProviderNames(providerName).build();
100            try {
101                if (MonetaryConversions.isConversionAvailable(query)) {
102                    CurrencyConversion conv = MonetaryConversions.getConversion(query);
103                    AssertJUnit.assertNotNull(
104                            "CurrencyConversion returned from MonetaryConversions.getConversion(ConversionQuery) must" +
105                                    " " +
106                                    "never be null: " +
107                                    providerName, conv);
108                    AssertJUnit
109                            .assertTrue("CurrencyConversion is not flagged as available though it was returned from " +
110                                    "MonetaryConversions.getConversion(ConversionQuery): " +
111                                    providerName, MonetaryConversions.isConversionAvailable(query));
112                }
113            } catch (MonetaryException e) {
114                // OK, possible!
115                AssertJUnit.assertFalse(
116                        "CurrencyConversion is not flagged as not available, though it was not returned from " +
117                                "MonetaryConversions.getConversion(ConversionQuery): " +
118                                providerName, MonetaryConversions.isConversionAvailable(query));
119            }
120        }
121    }
122
123    /**
124     * Test if all providers returns valid meta data.
125     *
126     * @see javax.money.convert.ProviderContext
127     */
128    @Test(description = "4.3.1 Test if all ExchangeRateProvider instances returns valid ProviderContext.")
129    @SpecAssertion(id = "431-A3", section = "4.3.1")
130    public void testProviderMetadata() {
131        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
132            ExchangeRateProvider prov = MonetaryConversions.getExchangeRateProvider(providerName);
133            AssertJUnit.assertNotNull("Provider mot accessible: " + providerName, prov);
134            ProviderContext ctx = prov.getContext();
135            AssertJUnit.assertNotNull(
136                    "ExchangeProvider must return a valid ProviderContext, but returned null: " + providerName, ctx);
137            AssertJUnit.assertEquals("ExchangeProvider's ProviderContext returns invalid name: " + providerName,
138                    providerName, ctx.getProviderName());
139            AssertJUnit.assertNotNull(
140                    "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): " +
141                            providerName, ctx.getRateTypes());
142            AssertJUnit.assertFalse(
143                    "ExchangeProvider's ProviderContext declares empty RateTypes to be returned: " + providerName,
144                    ctx.getRateTypes().isEmpty());
145        }
146    }
147
148    /**
149     * Test if all providers returns valid meta data.
150     *
151     * @see javax.money.convert.ProviderContext
152     */
153    @Test(description = "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by " +
154            "currency code.")
155    @SpecAssertion(id = "431-A3", section = "4.3.1")
156    public void testProviderMetadata2() {
157        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
158            if (MonetaryConversions.isConversionAvailable("XXX", providerName)) {
159                CurrencyConversion conv = MonetaryConversions.getConversion("XXX", providerName);
160                ConversionContext ctx = conv.getContext();
161                AssertJUnit.assertNotNull(
162                        "ExchangeProvider must return a valid ProviderContext, but returned null: " + providerName,
163                        ctx);
164                AssertJUnit.assertEquals("ExchangeProvider's ProviderContext returns invalid name: " + providerName,
165                        providerName, ctx.getProviderName());
166                AssertJUnit.assertNotNull(
167                        "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): " +
168                                providerName, ctx.getRateType());
169            }
170        }
171    }
172
173    /**
174     * Test if all providers returns valid meta data.
175     *
176     * @see javax.money.convert.ProviderContext
177     */
178    @Test(description = "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by " +
179            "CurrencyUnit.")
180    @SpecAssertion(id = "431-A3", section = "4.3.1")
181    public void testProviderMetadata3() {
182        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
183            if (MonetaryConversions.isConversionAvailable(Monetary.getCurrency("XXX"), providerName)) {
184                CurrencyConversion conv =
185                        MonetaryConversions.getConversion(Monetary.getCurrency("XXX"), providerName);
186                ConversionContext ctx = conv.getContext();
187                AssertJUnit.assertNotNull(
188                        "ExchangeProvider must return a valid ProviderContext, but returned null: " + providerName,
189                        ctx);
190                AssertJUnit.assertEquals("ExchangeProvider's ProviderContext returns invalid name: " + providerName,
191                        providerName, ctx.getProviderName());
192                AssertJUnit.assertNotNull(
193                        "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): " +
194                                providerName, ctx.getRateType());
195            }
196        }
197    }
198
199    /**
200     * Test if all providers returns valid meta data.
201     *
202     * @see javax.money.convert.ProviderContext
203     */
204    @Test(description = "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by " +
205            "ConversionQuery/currency code.")
206    @SpecAssertion(id = "431-A3", section = "4.3.1")
207    public void testProviderMetadata2WithContext() {
208        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
209            ConversionQuery query = ConversionQueryBuilder.of().
210                    setTermCurrency("XXX").setProviderNames(providerName).build();
211            if (MonetaryConversions.isConversionAvailable(query)) {
212                CurrencyConversion conv = MonetaryConversions.getConversion(query);
213                ConversionContext ctx = conv.getContext();
214                AssertJUnit.assertNotNull(
215                        "ExchangeProvider must return a valid ProviderContext, but returned null: " + providerName,
216                        ctx);
217                AssertJUnit.assertEquals("ExchangeProvider's ProviderContext returns invalid name: " + providerName,
218                        providerName, ctx.getProviderName());
219                AssertJUnit.assertNotNull(
220                        "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): " +
221                                providerName, ctx.getRateType());
222            }
223        }
224    }
225
226    /**
227     * Test if all providers returns valid meta data.
228     *
229     * @see javax.money.convert.ProviderContext
230     */
231    @Test(description = "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by " +
232            "ConversionQuery/CurrencyUnit.")
233    @SpecAssertion(id = "431-A3", section = "4.3.1")
234    public void testProviderMetadata3WithContext() {
235        for (String providerName : MonetaryConversions.getConversionProviderNames()) {
236            ConversionQuery query = ConversionQueryBuilder.of().
237                    setTermCurrency(Monetary.getCurrency("XXX")).setProviderName(providerName).build();
238            if (MonetaryConversions.isConversionAvailable(query)) {
239                CurrencyConversion conv = MonetaryConversions.getConversion(query);
240                ConversionContext ctx = conv.getContext();
241                AssertJUnit.assertNotNull(
242                        "ExchangeProvider must return a valid ProviderContext, but returned null: " + providerName,
243                        ctx);
244                AssertJUnit.assertEquals("ExchangeProvider's ProviderContext returns invalid name: " + providerName,
245                        providerName, ctx.getProviderName());
246                AssertJUnit.assertNotNull(
247                        "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): " +
248                                providerName, ctx.getRateType());
249            }
250        }
251    }
252
253
254    /**
255     * Access the default provider chain. Compare with entries from javamoney.properties. The chain must not be empty!
256     */
257    @Test(description = "4.3.1 Access and test the default conversion provider chain.")
258    @SpecAssertion(id = "431-A4", section = "4.3.1")
259    public void testDefaultProviderChainIsDefined() {
260        ExchangeRateProvider prov = MonetaryConversions.getExchangeRateProvider();
261        AssertJUnit.assertNotNull("No default ExchangeRateProvider returned.", prov);
262        // we cannot test more here...
263    }
264
265    /**
266     * Access the default provider chain. Compare with entries from javamoney.properties. The chain must not be empty!
267     */
268    @Test(description = "4.3.1 Access and test the default conversion provider chain, by accessing a default" +
269            "CurrencyConversion for term CurrencyUnit CHF.")
270    @SpecAssertion(id = "431-A4", section = "4.3.1")
271    public void testDefaultProviderChainIsDefinedDefault() {
272        CurrencyConversion conv = MonetaryConversions.getConversion(Monetary.getCurrency("CHF"));
273        AssertJUnit.assertNotNull("No default CurrencyConversion returned.", conv);
274        // we cannot test more here...
275    }
276
277    /**
278     * Access the default provider chain. Compare with entries from javamoney.properties. The chain must not be empty!
279     */
280    @Test(description = "4.3.1 Access and test the default conversion provider chain, by accessing a default" +
281            "CurrencyConversion for term currency code CHF.")
282    @SpecAssertion(id = "431-A4", section = "4.3.1")
283    public void testDefaultProviderChainIsDefinedDefault2() {
284        CurrencyConversion conv = MonetaryConversions.getConversion("CHF");
285        AssertJUnit.assertNotNull("No default CurrencyConversion returned.", conv);
286        // we cannot test more here...
287    }
288
289    /**
290     * Access the default provider chain. Compare with entries from javamoney.properties. The chain must not be empty!
291     */
292    @Test(description = "4.3.1 Access and test the default conversion provider chain, by accessing a default" +
293            "CurrencyConversion for ConversionQuery.")
294    @SpecAssertion(id = "431-A4", section = "4.3.1")
295    public void testDefaultProviderChainIsDefinedDefaultWithContext() {
296        ConversionQuery query =
297                ConversionQueryBuilder.of().setTermCurrency(Monetary.getCurrency("CHF")).build();
298        CurrencyConversion conv = MonetaryConversions.getConversion(query);
299        AssertJUnit.assertNotNull("No default CurrencyConversion returned.", conv);
300        // we cannot test more here...
301    }
302
303    /**
304     * Access the conversion using the default conversion chain.
305     */
306    @Test(description = "4.3.1 Access and test conversion using the default provider chain.")
307    @SpecAssertion(id = "431-A5", section = "4.3.1")
308    public void testDefaultConversion() {
309        ConversionQuery query =
310                ConversionQueryBuilder.of().setTermCurrency(Monetary.getCurrency("USD")).build();
311        CurrencyConversion conv = MonetaryConversions.getConversion(query);
312        AssertJUnit.assertNotNull("No default CurrencyConversion returned for USD.", conv);
313        query =
314                ConversionQueryBuilder.of().setTermCurrency(Monetary.getCurrency("EUR")).build();
315        conv = MonetaryConversions.getConversion(query);
316        AssertJUnit.assertNotNull("No default CurrencyConversion returned for EUR.", conv);
317    }
318
319
320    /**
321     * Bad case: Test access of an inexistent provider. Should throw a MonetaryException
322     */
323    @Test(expectedExceptions = MonetaryException.class, description = "4.3.1 Bad case: Access invalid " +
324            "ExchangeRateProvider, expect MonetaryException thrown, using default provider chain.")
325    @SpecAssertion(id = "431-A6", section = "4.3.1",
326            note = "Accessing an invalid provider name, should throw a MonetaryException.")
327    public void testUseInvalidProvider() {
328        MonetaryConversions.getExchangeRateProvider("Dhdkjdhskljdsudgsdkjgjk sgdsjdg");
329    }
330
331    /**
332     * Bad case: Test access of an inexistent provider within a chain of providers (all other providers must be valid).
333     * Should throw a MonetaryException
334     */
335    @Test(expectedExceptions = MonetaryException.class, description = "4.3.1 Bad case: Access invalid " +
336            "ExchangeRateProvider, expect MonetaryException thrown, using explicit provider.")
337    @SpecAssertion(id = "431-A7", section = "4.3.1",
338            note = "Accessing an invalid provider name within a name chain, should throw a MonetaryException.")
339    public void testUseInvalidProviderWithinChain() {
340        MonetaryConversions.getExchangeRateProvider("TestRateProvider", "Dhdkjdhskljdsudgsdkjgjk sgdsjdg");
341    }
342
343}