1 /* 2 * Copyright (c) 2011 Google, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.common.truth; 17 18 import static com.google.common.base.Preconditions.checkNotNull; 19 20 import com.google.common.annotations.GwtIncompatible; 21 import com.google.common.base.Optional; 22 import com.google.common.collect.ImmutableList; 23 import com.google.common.collect.Multimap; 24 import com.google.common.collect.Multiset; 25 import com.google.common.collect.Table; 26 import java.math.BigDecimal; 27 import java.util.Map; 28 import org.checkerframework.checker.nullness.qual.Nullable; 29 30 /** 31 * In a fluent assertion chain, an object with which you can do any of the following: 32 * 33 * <ul> 34 * <li>Set an optional message with {@link #withMessage}. 35 * <li>Specify the type of {@code Subject} to create with {@link #about(Subject.Factory)}. 36 * <li>For the types of {@code Subject} built into Truth, directly specify the value under test 37 * with {@link #that(Object)}. 38 * </ul> 39 * 40 * <p>For more information about the methods in this class, see <a 41 * href="https://truth.dev/faq#full-chain">this FAQ entry</a>. 42 * 43 * <h3>For people extending Truth</h3> 44 * 45 * <p>You won't extend this type. When you write a custom subject, see <a 46 * href="https://truth.dev/extension">our doc on extensions</a>. 47 */ 48 public class StandardSubjectBuilder { 49 /** 50 * Returns a new instance that invokes the given {@code FailureStrategy} when a check fails. Most 51 * users should not need this. If you think you do, see the documentation on {@link 52 * FailureStrategy}. 53 */ forCustomFailureStrategy(FailureStrategy failureStrategy)54 public static StandardSubjectBuilder forCustomFailureStrategy(FailureStrategy failureStrategy) { 55 return new StandardSubjectBuilder(FailureMetadata.forFailureStrategy(failureStrategy)); 56 } 57 58 private final FailureMetadata metadataDoNotReferenceDirectly; 59 StandardSubjectBuilder(FailureMetadata metadata)60 StandardSubjectBuilder(FailureMetadata metadata) { 61 this.metadataDoNotReferenceDirectly = checkNotNull(metadata); 62 } 63 64 @SuppressWarnings({"unchecked", "rawtypes"}) that( @ullable ComparableT actual)65 public final <ComparableT extends Comparable<?>> ComparableSubject<ComparableT> that( 66 @Nullable ComparableT actual) { 67 return new ComparableSubject(metadata(), actual) {}; 68 } 69 that(@ullable BigDecimal actual)70 public final BigDecimalSubject that(@Nullable BigDecimal actual) { 71 return new BigDecimalSubject(metadata(), actual); 72 } 73 that(@ullable Object actual)74 public final Subject that(@Nullable Object actual) { 75 return new Subject(metadata(), actual); 76 } 77 78 @GwtIncompatible("ClassSubject.java") that(@ullable Class<?> actual)79 public final ClassSubject that(@Nullable Class<?> actual) { 80 return new ClassSubject(metadata(), actual); 81 } 82 that(@ullable Throwable actual)83 public final ThrowableSubject that(@Nullable Throwable actual) { 84 return new ThrowableSubject(metadata(), actual, "throwable"); 85 } 86 that(@ullable Long actual)87 public final LongSubject that(@Nullable Long actual) { 88 return new LongSubject(metadata(), actual); 89 } 90 that(@ullable Double actual)91 public final DoubleSubject that(@Nullable Double actual) { 92 return new DoubleSubject(metadata(), actual); 93 } 94 that(@ullable Float actual)95 public final FloatSubject that(@Nullable Float actual) { 96 return new FloatSubject(metadata(), actual); 97 } 98 that(@ullable Integer actual)99 public final IntegerSubject that(@Nullable Integer actual) { 100 return new IntegerSubject(metadata(), actual); 101 } 102 that(@ullable Boolean actual)103 public final BooleanSubject that(@Nullable Boolean actual) { 104 return new BooleanSubject(metadata(), actual); 105 } 106 that(@ullable String actual)107 public final StringSubject that(@Nullable String actual) { 108 return new StringSubject(metadata(), actual); 109 } 110 that(@ullable Iterable<?> actual)111 public final IterableSubject that(@Nullable Iterable<?> actual) { 112 return new IterableSubject(metadata(), actual); 113 } 114 that(@ullable T [] actual)115 public final <T> ObjectArraySubject<T> that(@Nullable T /*@Nullable*/[] actual) { 116 return new ObjectArraySubject<>(metadata(), actual, "array"); 117 } 118 that(boolean [] actual)119 public final PrimitiveBooleanArraySubject that(boolean /*@Nullable*/[] actual) { 120 return new PrimitiveBooleanArraySubject(metadata(), actual, "array"); 121 } 122 that(short [] actual)123 public final PrimitiveShortArraySubject that(short /*@Nullable*/[] actual) { 124 return new PrimitiveShortArraySubject(metadata(), actual, "array"); 125 } 126 that(int [] actual)127 public final PrimitiveIntArraySubject that(int /*@Nullable*/[] actual) { 128 return new PrimitiveIntArraySubject(metadata(), actual, "array"); 129 } 130 that(long [] actual)131 public final PrimitiveLongArraySubject that(long /*@Nullable*/[] actual) { 132 return new PrimitiveLongArraySubject(metadata(), actual, "array"); 133 } 134 that(char [] actual)135 public final PrimitiveCharArraySubject that(char /*@Nullable*/[] actual) { 136 return new PrimitiveCharArraySubject(metadata(), actual, "array"); 137 } 138 that(byte [] actual)139 public final PrimitiveByteArraySubject that(byte /*@Nullable*/[] actual) { 140 return new PrimitiveByteArraySubject(metadata(), actual, "array"); 141 } 142 that(float [] actual)143 public final PrimitiveFloatArraySubject that(float /*@Nullable*/[] actual) { 144 return new PrimitiveFloatArraySubject(metadata(), actual, "array"); 145 } 146 that(double [] actual)147 public final PrimitiveDoubleArraySubject that(double /*@Nullable*/[] actual) { 148 return new PrimitiveDoubleArraySubject(metadata(), actual, "array"); 149 } 150 that(@ullable Optional<?> actual)151 public final GuavaOptionalSubject that(@Nullable Optional<?> actual) { 152 return new GuavaOptionalSubject(metadata(), actual, "optional"); 153 } 154 that(@ullable Map<?, ?> actual)155 public final MapSubject that(@Nullable Map<?, ?> actual) { 156 return new MapSubject(metadata(), actual); 157 } 158 that(@ullable Multimap<?, ?> actual)159 public final MultimapSubject that(@Nullable Multimap<?, ?> actual) { 160 return new MultimapSubject(metadata(), actual, "multimap"); 161 } 162 that(@ullable Multiset<?> actual)163 public final MultisetSubject that(@Nullable Multiset<?> actual) { 164 return new MultisetSubject(metadata(), actual); 165 } 166 that(@ullable Table<?, ?, ?> actual)167 public final TableSubject that(@Nullable Table<?, ?, ?> actual) { 168 return new TableSubject(metadata(), actual); 169 } 170 171 /** 172 * Returns a new instance that will output the given message before the main failure message. If 173 * this method is called multiple times, the messages will appear in the order that they were 174 * specified. 175 */ withMessage(@ullable String messageToPrepend)176 public final StandardSubjectBuilder withMessage(@Nullable String messageToPrepend) { 177 return withMessage("%s", messageToPrepend); 178 } 179 180 /** 181 * Returns a new instance that will output the given message before the main failure message. If 182 * this method is called multiple times, the messages will appear in the order that they were 183 * specified. 184 * 185 * <p><b>Note:</b> the arguments will be substituted into the format template using {@link 186 * com.google.common.base.Strings#lenientFormat Strings.lenientFormat}. Note this only supports 187 * the {@code %s} specifier. 188 * 189 * @throws IllegalArgumentException if the number of placeholders in the format string does not 190 * equal the number of given arguments 191 */ withMessage(String format, Object... args)192 public final StandardSubjectBuilder withMessage(String format, /*@Nullable*/ Object... args) { 193 return new StandardSubjectBuilder(metadata().withMessage(format, args)); 194 } 195 196 /** 197 * Given a factory for some {@code Subject} class, returns a builder whose {@code that(actual)} 198 * method creates instances of that class. Created subjects use the previously set failure 199 * strategy and any previously set failure message. 200 */ about( Subject.Factory<S, A> factory)201 public final <S extends Subject, A> SimpleSubjectBuilder<S, A> about( 202 Subject.Factory<S, A> factory) { 203 return new SimpleSubjectBuilder<>(metadata(), factory); 204 } 205 about( CustomSubjectBuilder.Factory<CustomSubjectBuilderT> factory)206 public final <CustomSubjectBuilderT extends CustomSubjectBuilder> CustomSubjectBuilderT about( 207 CustomSubjectBuilder.Factory<CustomSubjectBuilderT> factory) { 208 return factory.createSubjectBuilder(metadata()); 209 } 210 211 /** 212 * Reports a failure. 213 * 214 * <p>To set a message, first call {@link #withMessage} (or, more commonly, use the shortcut 215 * {@link Truth#assertWithMessage}). 216 */ fail()217 public final void fail() { 218 metadata().fail(ImmutableList.<Fact>of()); 219 } 220 metadata()221 private FailureMetadata metadata() { 222 checkStatePreconditions(); 223 return metadataDoNotReferenceDirectly; 224 } 225 226 /** 227 * Extension point invoked before every assertion. This allows {@link Expect} to check that it's 228 * been set up properly as a {@code TestRule}. 229 */ checkStatePreconditions()230 void checkStatePreconditions() {} 231 } 232