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 that( @ullable ComparableT actual)64 public final <ComparableT extends Comparable<?>> ComparableSubject<ComparableT> that( 65 @Nullable ComparableT actual) { 66 return new ComparableSubject<ComparableT>(metadata(), actual) {}; 67 } 68 that(@ullable BigDecimal actual)69 public final BigDecimalSubject that(@Nullable BigDecimal actual) { 70 return new BigDecimalSubject(metadata(), actual); 71 } 72 that(@ullable Object actual)73 public final Subject that(@Nullable Object actual) { 74 return new Subject(metadata(), actual); 75 } 76 77 @GwtIncompatible("ClassSubject.java") 78 @J2ktIncompatible 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 115 @SuppressWarnings("AvoidObjectArrays") that(@ullable T @ullable [] actual)116 public final <T> ObjectArraySubject<T> that(@Nullable T @Nullable [] actual) { 117 return new ObjectArraySubject<>(metadata(), actual, "array"); 118 } 119 that(boolean @Nullable [] actual)120 public final PrimitiveBooleanArraySubject that(boolean @Nullable [] actual) { 121 return new PrimitiveBooleanArraySubject(metadata(), actual, "array"); 122 } 123 that(short @Nullable [] actual)124 public final PrimitiveShortArraySubject that(short @Nullable [] actual) { 125 return new PrimitiveShortArraySubject(metadata(), actual, "array"); 126 } 127 that(int @Nullable [] actual)128 public final PrimitiveIntArraySubject that(int @Nullable [] actual) { 129 return new PrimitiveIntArraySubject(metadata(), actual, "array"); 130 } 131 that(long @Nullable [] actual)132 public final PrimitiveLongArraySubject that(long @Nullable [] actual) { 133 return new PrimitiveLongArraySubject(metadata(), actual, "array"); 134 } 135 that(char @Nullable [] actual)136 public final PrimitiveCharArraySubject that(char @Nullable [] actual) { 137 return new PrimitiveCharArraySubject(metadata(), actual, "array"); 138 } 139 that(byte @Nullable [] actual)140 public final PrimitiveByteArraySubject that(byte @Nullable [] actual) { 141 return new PrimitiveByteArraySubject(metadata(), actual, "array"); 142 } 143 that(float @Nullable [] actual)144 public final PrimitiveFloatArraySubject that(float @Nullable [] actual) { 145 return new PrimitiveFloatArraySubject(metadata(), actual, "array"); 146 } 147 that(double @Nullable [] actual)148 public final PrimitiveDoubleArraySubject that(double @Nullable [] actual) { 149 return new PrimitiveDoubleArraySubject(metadata(), actual, "array"); 150 } 151 that(@ullable Optional<?> actual)152 public final GuavaOptionalSubject that(@Nullable Optional<?> actual) { 153 return new GuavaOptionalSubject(metadata(), actual, "optional"); 154 } 155 that(@ullable Map<?, ?> actual)156 public final MapSubject that(@Nullable Map<?, ?> actual) { 157 return new MapSubject(metadata(), actual); 158 } 159 that(@ullable Multimap<?, ?> actual)160 public final MultimapSubject that(@Nullable Multimap<?, ?> actual) { 161 return new MultimapSubject(metadata(), actual, "multimap"); 162 } 163 that(@ullable Multiset<?> actual)164 public final MultisetSubject that(@Nullable Multiset<?> actual) { 165 return new MultisetSubject(metadata(), actual); 166 } 167 that(@ullable Table<?, ?, ?> actual)168 public final TableSubject that(@Nullable Table<?, ?, ?> actual) { 169 return new TableSubject(metadata(), actual); 170 } 171 172 /** 173 * Returns a new instance that will output the given message before the main failure message. If 174 * this method is called multiple times, the messages will appear in the order that they were 175 * specified. 176 */ withMessage(@ullable String messageToPrepend)177 public final StandardSubjectBuilder withMessage(@Nullable String messageToPrepend) { 178 return withMessage("%s", messageToPrepend); 179 } 180 181 /** 182 * Returns a new instance that will output the given message before the main failure message. If 183 * this method is called multiple times, the messages will appear in the order that they were 184 * specified. 185 * 186 * <p><b>Note:</b> the arguments will be substituted into the format template using {@link 187 * com.google.common.base.Strings#lenientFormat Strings.lenientFormat}. Note this only supports 188 * the {@code %s} specifier. 189 * 190 * @throws IllegalArgumentException if the number of placeholders in the format string does not 191 * equal the number of given arguments 192 */ withMessage(String format, @Nullable Object... args)193 public final StandardSubjectBuilder withMessage(String format, @Nullable Object... args) { 194 return new StandardSubjectBuilder(metadata().withMessage(format, args)); 195 } 196 197 /** 198 * Given a factory for some {@code Subject} class, returns a builder whose {@code that(actual)} 199 * method creates instances of that class. Created subjects use the previously set failure 200 * strategy and any previously set failure message. 201 */ about( Subject.Factory<S, A> factory)202 public final <S extends Subject, A> SimpleSubjectBuilder<S, A> about( 203 Subject.Factory<S, A> factory) { 204 return new SimpleSubjectBuilder<>(metadata(), factory); 205 } 206 about( CustomSubjectBuilder.Factory<CustomSubjectBuilderT> factory)207 public final <CustomSubjectBuilderT extends CustomSubjectBuilder> CustomSubjectBuilderT about( 208 CustomSubjectBuilder.Factory<CustomSubjectBuilderT> factory) { 209 return factory.createSubjectBuilder(metadata()); 210 } 211 212 /** 213 * Reports a failure. 214 * 215 * <p>To set a message, first call {@link #withMessage} (or, more commonly, use the shortcut 216 * {@link Truth#assertWithMessage}). 217 */ fail()218 public final void fail() { 219 metadata().fail(ImmutableList.<Fact>of()); 220 } 221 metadata()222 private FailureMetadata metadata() { 223 checkStatePreconditions(); 224 return metadataDoNotReferenceDirectly; 225 } 226 227 /** 228 * Extension point invoked before every assertion. This allows {@link Expect} to check that it's 229 * been set up properly as a {@code TestRule}. 230 */ checkStatePreconditions()231 void checkStatePreconditions() {} 232 } 233