Formats the given messages and facts into a string for use as the message of a test failure. In particular, this method horizontally aligns the beginning of fact values.
(List<String> messages, List<Fact> facts)
| 188 | * particular, this method horizontally aligns the beginning of fact values. |
| 189 | */ |
| 190 | static String makeMessage(List<String> messages, List<Fact> facts) { |
| 191 | int longestKeyLength = 0; |
| 192 | int longestIntPartValueLength = 0; |
| 193 | boolean seenNewlineInValue = false; |
| 194 | for (Fact fact : facts) { |
| 195 | if (fact.value != null) { |
| 196 | longestKeyLength = max(longestKeyLength, fact.key.length()); |
| 197 | if (fact.padStart) { |
| 198 | int decimalIndex = fact.value.indexOf('.'); |
| 199 | if (decimalIndex != -1) { |
| 200 | longestIntPartValueLength = max(longestIntPartValueLength, decimalIndex); |
| 201 | } else { |
| 202 | longestIntPartValueLength = max(longestIntPartValueLength, fact.value.length()); |
| 203 | } |
| 204 | } |
| 205 | // TODO(cpovirk): Look for other kinds of newlines. |
| 206 | seenNewlineInValue |= fact.value.contains("\n"); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | StringBuilder builder = new StringBuilder(); |
| 211 | for (String message : messages) { |
| 212 | builder.append(message); |
| 213 | builder.append('\n'); |
| 214 | } |
| 215 | |
| 216 | /* |
| 217 | * *Usually* the first fact is printed at the beginning of a new line. However, when this |
| 218 | * exception is the cause of another exception, that exception will print it starting after |
| 219 | * "Caused by: " on the same line. The other exception sometimes also reuses this message as its |
| 220 | * own message. In both of those scenarios, the first line doesn't start at column 0, so the |
| 221 | * horizontal alignment is thrown off. |
| 222 | * |
| 223 | * There's not much we can do about this, short of always starting with a newline (which would |
| 224 | * leave a blank line at the beginning of the message in the normal case). |
| 225 | */ |
| 226 | for (Fact fact : facts) { |
| 227 | if (fact.value == null) { |
| 228 | builder.append(fact.key); |
| 229 | } else if (seenNewlineInValue) { |
| 230 | builder.append(fact.key); |
| 231 | builder.append(":\n"); |
| 232 | builder.append(indent(fact.value)); |
| 233 | } else { |
| 234 | builder.append(padEnd(fact.key, longestKeyLength, ' ')); |
| 235 | builder.append(": "); |
| 236 | if (fact.padStart) { |
| 237 | int decimalIndex = fact.value.indexOf('.'); |
| 238 | if (decimalIndex != -1) { |
| 239 | builder.append( |
| 240 | padStart(fact.value.substring(0, decimalIndex), longestIntPartValueLength, ' ')); |
| 241 | builder.append(fact.value.substring(decimalIndex)); |
| 242 | } else { |
| 243 | builder.append(padStart(fact.value, longestIntPartValueLength, ' ')); |
| 244 | } |
| 245 | } else { |
| 246 | builder.append(fact.value); |
| 247 | } |