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.bifunction; 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025import java.util.Objects; 026import java.util.function.BiFunction; 027import java.util.function.Supplier; 028 029import org.hamcrest.Matcher; 030 031import ch.powerunit.TestInterface; 032import ch.powerunit.bifunction.impl.BiFunctionTesterImpl; 033import ch.powerunit.bifunction.lang.BiFunctionTesterDefineDSL; 034import ch.powerunit.bifunction.lang.BiFunctionTesterEndDSL; 035import ch.powerunit.bifunction.lang.BiFunctionTesterNextDSL; 036import ch.powerunit.bifunction.lang.BiFunctionTesterStartDSL; 037import ch.powerunit.function.impl.SupplierEqualsToMatcher; 038 039/** 040 * Tester for bifunction. 041 * 042 * @author borettim 043 * @since 0.3.0 044 */ 045@TestInterface(BiFunctionTesterImpl.class) 046public final class BiFunctionTester<T, U, R> { 047 private final BiFunction<T, U, R> underTest; 048 private final List<Supplier<T>> input1; 049 private final List<Supplier<U>> input2; 050 private final List<Supplier<Matcher<? super R>>> result; 051 private final List<Supplier<String>> name; 052 053 private static class BiFunctionTesterDSL<T, U, R> implements 054 BiFunctionTesterDefineDSL<T, U, R>, 055 BiFunctionTesterEndDSL<T, U, R>, BiFunctionTesterNextDSL<T, U, R>, 056 BiFunctionTesterStartDSL<T, U, R> { 057 058 private final BiFunction<T, U, R> underTest; 059 060 private List<Supplier<T>> tmpInput1 = new ArrayList<>(); 061 062 private List<Supplier<U>> tmpInput2 = new ArrayList<>(); 063 064 private List<Supplier<Matcher<? super R>>> tmpResult = new ArrayList<>(); 065 066 private List<Supplier<String>> tmpName = new ArrayList<>(); 067 068 private void finalizeCase() { 069 if (tmpName.size() < tmpInput1.size()) { 070 tmpName.add(() -> ""); 071 } 072 } 073 074 public BiFunctionTesterDSL(BiFunction<T, U, R> underTest) { 075 this.underTest = underTest; 076 } 077 078 @Override 079 public BiFunctionTesterDefineDSL<T, U, R> passingAsParameter(T input1, 080 U input2) { 081 return passingAsParameter(() -> input1, () -> input2); 082 } 083 084 @Override 085 public BiFunctionTesterDefineDSL<T, U, R> passingAsParameter( 086 Supplier<T> input1, Supplier<U> input2) { 087 Objects.requireNonNull(input1, "input1 can't be null"); 088 Objects.requireNonNull(input2, "input2 can't be null"); 089 finalizeCase(); 090 tmpInput1.add(input1); 091 tmpInput2.add(input2); 092 return this; 093 } 094 095 @Override 096 public BiFunctionTesterNextDSL<T, U, R> thenExpectingResult(R result) { 097 return thenExpectingResult(() -> result); 098 } 099 100 @Override 101 public BiFunctionTesterNextDSL<T, U, R> thenExpectingResult( 102 Supplier<R> result) { 103 Objects.requireNonNull(result, "matching can't be null"); 104 return thenExpectingResultThat(new SupplierEqualsToMatcher<R>( 105 result)); 106 } 107 108 @Override 109 public BiFunctionTesterNextDSL<T, U, R> thenExpectingResultThat( 110 Matcher<? super R> matching) { 111 Objects.requireNonNull(matching, "matching can't be null"); 112 return thenExpectingResultThat(() -> matching); 113 } 114 115 @Override 116 public BiFunctionTesterNextDSL<T, U, R> thenExpectingResultThat( 117 Supplier<Matcher<? super R>> matching) { 118 Objects.requireNonNull(matching, "matching can't be null"); 119 tmpResult.add(matching); 120 return this; 121 } 122 123 @Override 124 public BiFunctionTesterEndDSL<T, U, R> testNamed(String name) { 125 return testNamed(() -> name); 126 } 127 128 @Override 129 public BiFunctionTesterEndDSL<T, U, R> testNamed(Supplier<String> name) { 130 Objects.requireNonNull(name, "name can't be null"); 131 tmpName.add(name); 132 return this; 133 } 134 135 @Override 136 public BiFunctionTester<T, U, R> build() { 137 finalizeCase(); 138 return new BiFunctionTester<T, U, R>(underTest, tmpInput1, 139 tmpInput2, tmpResult, tmpName); 140 } 141 } 142 143 private BiFunctionTester(BiFunction<T, U, R> underTest, 144 List<Supplier<T>> tmpInput1, List<Supplier<U>> tmpInput2, 145 List<Supplier<Matcher<? super R>>> tmpResult, 146 List<Supplier<String>> tmpName) { 147 this.underTest = underTest; 148 this.input1 = tmpInput1; 149 this.input2 = tmpInput2; 150 this.result = tmpResult; 151 this.name = tmpName; 152 } 153 154 /** 155 * Start the creation of a tester of function. 156 * <p> 157 * For example : 158 * 159 * <pre> 160 * @TestDelegate 161 * public final BiFunctionTester<Short, Integer, Long> tester1 = BiFunctionTester 162 * .of(this::bifunctionToBeTested).passingAsParameter((short) 1, 2) 163 * .thenExpectingResult(3l).testNamed("tested") 164 * .passingAsParameter((short) 2, 4).thenExpectingResult(6l).build(); 165 * </pre> 166 * 167 * @param bifunctionUnderTest 168 * the function to be tested 169 * @return {@link BiFunctionTesterStartDSL the DSL} 170 * @throws NullPointerException 171 * when bifunctionUnderTest is null 172 * @param <T> 173 * the first input argument type 174 * @param <U> 175 * the second input argument type 176 * @param <R> 177 * the result type 178 * @see ch.powerunit.TestDelegate 179 */ 180 public static <T, U, R> BiFunctionTesterStartDSL<T, U, R> of( 181 BiFunction<T, U, R> bifunctionUnderTest) { 182 Objects.requireNonNull(bifunctionUnderTest, 183 "bifunctionUnderTest can't be null"); 184 return new BiFunctionTesterDSL<T, U, R>(bifunctionUnderTest); 185 } 186 187 /** 188 * Used by the framework. 189 * 190 * @return the underTest 191 */ 192 public BiFunction<T, U, R> getUnderTest() { 193 return underTest; 194 } 195 196 /** 197 * Used by the framework. 198 * 199 * @return the first input 200 */ 201 public List<Supplier<T>> getInput1() { 202 return Collections.unmodifiableList(input1); 203 } 204 205 /** 206 * Used by the framework. 207 * 208 * @return the first input 209 */ 210 public List<Supplier<U>> getInput2() { 211 return Collections.unmodifiableList(input2); 212 } 213 214 /** 215 * Used by the framework. 216 * 217 * @return the result 218 */ 219 public List<Supplier<Matcher<? super R>>> getResult() { 220 return Collections.unmodifiableList(result); 221 } 222 223 /** 224 * Used by the framework. 225 * 226 * @return the name 227 */ 228 public List<Supplier<String>> getName() { 229 return Collections.unmodifiableList(name); 230 } 231 232}