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