001/**
002 * Powerunit - A JDK1.8 test framework
003 * Copyright (C) 2014 Mathieu Boretti.
004 *
005 * This file is part of Powerunit
006 *
007 * Powerunit is free software: you can redistribute it and/or modify
008 * it under the terms of the GNU General Public License as published by
009 * the Free Software Foundation, either version 3 of the License, or
010 * (at your option) any later version.
011 *
012 * Powerunit is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with Powerunit. If not, see <http://www.gnu.org/licenses/>.
019 */
020package ch.powerunit.comparator;
021
022import java.util.Comparator;
023import java.util.Objects;
024import java.util.function.Supplier;
025
026import ch.powerunit.TestInterface;
027import ch.powerunit.comparator.impl.ComparatorTesterImpl;
028import ch.powerunit.comparator.impl.SampleProvider;
029import ch.powerunit.comparator.lang.ComparatorTesterDSLEnd;
030import ch.powerunit.comparator.lang.ComparatorTesterDSLEquals;
031import ch.powerunit.comparator.lang.ComparatorTesterDSLGreater;
032import ch.powerunit.comparator.lang.ComparatorTesterDSLLess;
033import ch.powerunit.comparator.lang.ComparatorTesterDSLStart;
034
035/**
036 * This is a framework to simplify the testing of {@link Comparator}.
037 * 
038 * @author borettim
039 * @since 0.3.0
040 * @param <O>
041 *            The object of the comparator
042 * @param <C>
043 *            The comparator undertest
044 */
045@TestInterface(ComparatorTesterImpl.class)
046public final class ComparatorTester<O, C extends Comparator<O>> {
047        private static class ComparatorTesterDSL<O, C extends Comparator<O>>
048                        implements ComparatorTesterDSLStart<O, C>,
049                        ComparatorTesterDSLLess<O, C>, ComparatorTesterDSLEquals<O, C>,
050                        ComparatorTesterDSLGreater<O, C>, ComparatorTesterDSLEnd<O, C> {
051                private final Class<C> clazzUnderTest;
052                private O lessSamples[];
053                private O equalSamples[];
054                private O greaterSamples[];
055                private C underTest;
056
057                public ComparatorTesterDSL(Class<C> clazzUnderTest) {
058                        this.clazzUnderTest = clazzUnderTest;
059                }
060
061                @Override
062                public ComparatorTesterDSLEquals<O, C> withLessSamples(O... lessSamples) {
063                        this.lessSamples = lessSamples;
064                        return this;
065                }
066
067                @SuppressWarnings("unchecked")
068                @Override
069                public ComparatorTesterDSLEquals<O, C> withLessSamples(O first) {
070                        return withLessSamples((O[]) new Object[] { first });
071                }
072
073                @SuppressWarnings("unchecked")
074                @Override
075                public ComparatorTesterDSLEquals<O, C> withLessSamples(O first, O second) {
076                        return withLessSamples((O[]) new Object[] { first, second });
077                }
078
079                @SuppressWarnings("unchecked")
080                @Override
081                public ComparatorTesterDSLEquals<O, C> withLessSamples(O first,
082                                O second, O third) {
083                        return withLessSamples((O[]) new Object[] { first, second, third });
084                }
085
086                @SuppressWarnings("unchecked")
087                @Override
088                public ComparatorTesterDSLEquals<O, C> withLessSamples(O first,
089                                O second, O third, O fourth) {
090                        return withLessSamples((O[]) new Object[] { first, second, third,
091                                        fourth });
092                }
093
094                @Override
095                public ComparatorTesterDSLGreater<O, C> withEqualSamples(
096                                O... equalSamples) {
097                        this.equalSamples = equalSamples;
098                        return this;
099                }
100
101                @SuppressWarnings("unchecked")
102                @Override
103                public ComparatorTesterDSLGreater<O, C> withEqualSamples(O first) {
104                        return withEqualSamples((O[]) new Object[] { first });
105                }
106
107                @SuppressWarnings("unchecked")
108                @Override
109                public ComparatorTesterDSLGreater<O, C> withEqualSamples(O first,
110                                O second) {
111                        return withEqualSamples((O[]) new Object[] { first, second });
112                }
113
114                @SuppressWarnings("unchecked")
115                @Override
116                public ComparatorTesterDSLGreater<O, C> withEqualSamples(O first,
117                                O second, O third) {
118                        return withEqualSamples((O[]) new Object[] { first, second, third });
119                }
120
121                @SuppressWarnings("unchecked")
122                @Override
123                public ComparatorTesterDSLGreater<O, C> withEqualSamples(O first,
124                                O second, O third, O fourth) {
125                        return withEqualSamples((O[]) new Object[] { first, second, third,
126                                        fourth });
127                }
128
129                @Override
130                public ComparatorTesterDSLEnd<O, C> withGreaterSamples(
131                                O... greaterSamples) {
132                        this.greaterSamples = greaterSamples;
133                        return this;
134                }
135
136                @SuppressWarnings("unchecked")
137                @Override
138                public ComparatorTesterDSLEnd<O, C> withGreaterSamples(O first) {
139                        return withGreaterSamples((O[]) new Object[] { first });
140                }
141
142                @SuppressWarnings("unchecked")
143                @Override
144                public ComparatorTesterDSLEnd<O, C> withGreaterSamples(O first, O second) {
145                        return withGreaterSamples((O[]) new Object[] { first, second });
146                }
147
148                @SuppressWarnings("unchecked")
149                @Override
150                public ComparatorTesterDSLEnd<O, C> withGreaterSamples(O first,
151                                O second, O third) {
152                        return withGreaterSamples((O[]) new Object[] { first, second, third });
153                }
154
155                @SuppressWarnings("unchecked")
156                @Override
157                public ComparatorTesterDSLEnd<O, C> withGreaterSamples(O first,
158                                O second, O third, O fourth) {
159                        return withGreaterSamples((O[]) new Object[] { first, second,
160                                        third, fourth });
161                }
162
163                @Override
164                public ComparatorTesterDSLLess<O, C> usingInstance(C instance) {
165                        Objects.requireNonNull(instance, "instance can't be null");
166                        this.underTest = instance;
167                        return this;
168                }
169
170                @Override
171                public ComparatorTester<O, C> build() {
172                        Supplier<C> comparatorSupplier;
173                        if (underTest == null) {
174                                comparatorSupplier = () -> {
175                                        try {
176                                                return clazzUnderTest.newInstance();
177                                        } catch (InstantiationException | IllegalAccessException e) {
178                                                throw new IllegalArgumentException(
179                                                                "Unable to instanciate the class underTest using the default constructor. Use the usingInstance method to provide an instance",
180                                                                e);
181                                        }
182                                };
183                        } else {
184                                comparatorSupplier = () -> underTest;
185                        }
186                        Supplier<O[]> lessSupplier;
187                        Supplier<O[]> equalsSupplier;
188                        Supplier<O[]> greatSupplier;
189                        if (lessSamples == null) {
190                                SampleProvider<O, C> providers = new SampleProvider<O, C>(
191                                                clazzUnderTest, comparatorSupplier);
192                                lessSupplier = providers::getLessSamples;
193                                equalsSupplier = providers::getEqualSamples;
194                                greatSupplier = providers::getGreaterSamples;
195                        } else {
196                                lessSupplier = () -> lessSamples;
197                                equalsSupplier = () -> equalSamples;
198                                greatSupplier = () -> greaterSamples;
199                        }
200                        return new ComparatorTester<O, C>(clazzUnderTest, lessSupplier,
201                                        equalsSupplier, greatSupplier, comparatorSupplier);
202                }
203        }
204
205        private final Class<C> comparatorClass;
206
207        private final Supplier<O[]> lessSamples;
208
209        private final Supplier<O[]> equalSamples;
210
211        private final Supplier<O[]> greaterSamples;
212
213        private final Supplier<C> underTest;
214
215        private ComparatorTester(Class<C> comparatorClass,
216                        Supplier<O[]> lessSamples, Supplier<O[]> equalSamples,
217                        Supplier<O[]> greaterSamples, Supplier<C> underTest) {
218                this.comparatorClass = comparatorClass;
219                this.lessSamples = lessSamples;
220                this.equalSamples = equalSamples;
221                this.greaterSamples = greaterSamples;
222                this.underTest = underTest;
223        }
224
225        /**
226         * Use this method to start the DSL to test a comparator.
227         * <p>
228         * For example :
229         * 
230         * <pre>
231         * &#064;TestDelegate
232         * public final ComparatorTester&lt;Integer, MyComparator&gt; direct = ComparatorTester.of(
233         *              MyComparator.class).withLessSamples(-6).withEqualSamples(12)
234         *              .withGreaterSamples(16).build();
235         * </pre>
236         * 
237         * @param clazzUnderTest
238         *            The class of the comparator to be tested.
239         * @return {@link ComparatorTesterDSLStart the following of the DSL}
240         * @throws NullPointerException
241         *             when clazzUnderTest is null
242         * @param <O>
243         *            The object of the comparator
244         * @param <C>
245         *            The comparator undertest
246         * @see ch.powerunit.TestDelegate
247         */
248        public static <O, C extends Comparator<O>> ComparatorTesterDSLStart<O, C> of(
249                        final Class<C> clazzUnderTest) {
250                Objects.requireNonNull(clazzUnderTest, "clazzUnderTest can't be null");
251                return new ComparatorTesterDSL<O, C>(clazzUnderTest);
252        }
253
254        /**
255         * Used by the framework.
256         * 
257         * @return the comparatorClass
258         */
259        public Class<C> getComparatorClass() {
260                return comparatorClass;
261        }
262
263        /**
264         * Used by the framework.
265         * 
266         * @return the lessSamples
267         */
268        public Supplier<O[]> getLessSamples() {
269                return lessSamples;
270        }
271
272        /**
273         * Used by the framework.
274         * 
275         * @return the equalSamples
276         */
277        public Supplier<O[]> getEqualSamples() {
278                return equalSamples;
279        }
280
281        /**
282         * Used by the framework.
283         * 
284         * @return the greaterSamples
285         */
286        public Supplier<O[]> getGreaterSamples() {
287                return greaterSamples;
288        }
289
290        /**
291         * Used by the framework.
292         * 
293         * @return the underTest
294         */
295        public Supplier<C> getUnderTest() {
296                return underTest;
297        }
298}