001/*
002 * Units of Measurement API
003 * Copyright (c) 2014-2023, Jean-Marie Dautelle, Werner Keil, Otavio Santana.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385 nor the names of its contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package javax.measure.spi;
031
032import jakarta.inject.Named;
033import org.junit.jupiter.api.Test;
034
035import static org.junit.jupiter.api.Assertions.*;
036
037import java.util.Collection;
038
039import javax.measure.BinaryPrefix;
040import javax.measure.MetricPrefix;
041import javax.measure.Prefix;
042import javax.measure.Quantity;
043
044/**
045 * Tests for {@link ServiceProvider}.
046 */
047public class ServiceProviderTest {
048
049    @Test
050    public void testSetCurrentNull() {
051        assertThrows(NullPointerException.class, () -> {
052            ServiceProvider.setCurrent(null);
053        });
054    }
055
056    /**
057     * Tests {@link ServiceProvider#current()} and {@link ServiceProvider#setCurrent(ServiceProvider)}. The getter and setter are tested in a single
058     * method for avoiding issues with the order in which JUnit executes tests.
059     */
060    @Test
061    public void testGetAndSetCurrent() {
062        assertEquals(0, ServiceProvider.available().size());
063        try {
064            ServiceProvider.current();
065            fail("Expected no ServiceProvider before we set one.");
066        } catch (IllegalStateException e) {
067            // This is the expected exception.
068        }
069        ServiceProvider testProv = new TestServiceProvider();
070        assertNull(ServiceProvider.setCurrent(testProv), "Expected no ServiceProvider before we set one.");
071        assertSame(testProv, ServiceProvider.setCurrent(testProv), "Setting the same ServiceProvider twice should be a no-op.");
072        assertSame(testProv, ServiceProvider.current());
073        assertArrayEquals(new ServiceProvider[] { testProv }, ServiceProvider.available().toArray());
074        assertNotNull(ServiceProvider.of("Dummy ServiceProvider"));
075    }
076
077    /**
078     * Tests {@link ServiceProvider#getPriority()}.
079     */
080    @Test
081    public void testPriority() {
082        assertEquals(0, ServiceProvider.current().getPriority());
083    }
084
085    /**
086     * Tests ServiceProvider#of() by passing null.
087     */
088    @Test
089    public void testOfNull() {
090        assertThrows(NullPointerException.class, () -> {
091            @SuppressWarnings("unused")
092            ServiceProvider dummy = ServiceProvider.of(null);
093        });
094    }
095
096    /**
097     * Tests ServiceProvider#of() by passing a non-existing name.
098     */
099    @Test
100    public void testOfNonExistent() {
101        assertThrows(IllegalArgumentException.class, () -> {
102            @SuppressWarnings("unused")
103            ServiceProvider dummy = ServiceProvider.of("ThisServiceProviderWillNeverExistHere");
104        });
105    }
106
107    @Test
108    public void testGetMetricPrefixes() {
109        final ServiceProvider testProv = new TestServiceProvider();
110        final SystemOfUnitsService service = testProv.getSystemOfUnitsService();
111        Collection<MetricPrefix> prefixes = service.getPrefixes(MetricPrefix.class);
112        assertNotNull(prefixes);
113        assertEquals(24, prefixes.size());
114    }
115
116    @Test
117    public void testGetBinaryPrefixes() {
118        final ServiceProvider testProv = new TestServiceProvider();
119        final SystemOfUnitsService service = testProv.getSystemOfUnitsService();
120        assertNotNull(service);
121        Collection<BinaryPrefix> prefixes = service.getPrefixes(BinaryPrefix.class);
122        assertNotNull(prefixes);
123        assertEquals(8, prefixes.size());
124    }
125
126    @Test
127    public void testWrongPrefixType() {
128        final ServiceProvider testProv = new TestServiceProvider();
129        final SystemOfUnitsService service = testProv.getSystemOfUnitsService();
130        assertNotNull(service);
131        assertThrows(ClassCastException.class, () -> {
132            @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
133            Collection<Prefix> prefixes = service.getPrefixes((Class) String.class);
134        });
135
136    }
137
138    @Test
139    public void testWrongEnumType() {
140        final ServiceProvider testProv = new TestServiceProvider();
141        final SystemOfUnitsService service = testProv.getSystemOfUnitsService();
142        assertNotNull(service);
143        assertThrows(ClassCastException.class, () -> {
144            @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
145            Collection<Prefix> prefixes = service.getPrefixes((Class) DummyEnum.class);
146        });
147    }
148
149    @Named("Dummy ServiceProvider")     // Intentionally use a name different than "TestServiceProvider".
150    private static final class TestServiceProvider extends ServiceProvider {
151
152        @Override
153        public SystemOfUnitsService getSystemOfUnitsService() {
154            return new TestSystemOfUnitsService();
155        }
156
157        @Override
158        public <Q extends Quantity<Q>> QuantityFactory<Q> getQuantityFactory(Class<Q> quantity) {
159            return null;
160        }
161
162        @Override
163        public FormatService getFormatService() {
164            return null;
165        }
166
167        @Override
168        public String toString() {
169            return "TestServiceProvider";
170        }
171    }
172
173    private static enum DummyEnum {
174        A, B
175    }
176}