Line data Source code
1 : // Copyright (C) 2018 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.git.testing; 16 : 17 : import static com.google.common.base.Preconditions.checkArgument; 18 : import static com.google.common.truth.Fact.fact; 19 : import static com.google.common.truth.Truth.assertAbout; 20 : import static com.google.gerrit.git.testing.PushResultSubject.RemoteRefUpdateSubject.refs; 21 : 22 : import com.google.common.annotations.VisibleForTesting; 23 : import com.google.common.base.Splitter; 24 : import com.google.common.base.Strings; 25 : import com.google.common.base.Throwables; 26 : import com.google.common.collect.ImmutableMap; 27 : import com.google.common.collect.Maps; 28 : import com.google.common.truth.FailureMetadata; 29 : import com.google.common.truth.StreamSubject; 30 : import com.google.common.truth.Subject; 31 : import com.google.gerrit.common.Nullable; 32 : import org.eclipse.jgit.transport.PushResult; 33 : import org.eclipse.jgit.transport.RemoteRefUpdate; 34 : 35 : public class PushResultSubject extends Subject { 36 : public static PushResultSubject assertThat(PushResult actual) { 37 1 : return assertAbout(PushResultSubject::new).that(actual); 38 : } 39 : 40 : private final PushResult pushResult; 41 : 42 : private PushResultSubject(FailureMetadata metadata, PushResult pushResult) { 43 1 : super(metadata, pushResult); 44 1 : this.pushResult = pushResult; 45 1 : } 46 : 47 : public void hasNoMessages() { 48 1 : isNotNull(); 49 1 : check("hasNoMessages()").that(Strings.nullToEmpty(getTrimmedMessages())).isEqualTo(""); 50 1 : } 51 : 52 : public void hasMessages(String... expectedLines) { 53 1 : checkArgument(expectedLines.length > 0, "use hasNoMessages()"); 54 1 : isNotNull(); 55 1 : check("getTrimmedMessages()") 56 1 : .that(getTrimmedMessages()) 57 1 : .isEqualTo(String.join("\n", expectedLines)); 58 1 : } 59 : 60 : public void containsMessages(String... expectedLines) { 61 1 : checkArgument(expectedLines.length > 0, "use hasNoMessages()"); 62 1 : isNotNull(); 63 1 : Iterable<String> got = Splitter.on("\n").split(getTrimmedMessages()); 64 1 : check("getTrimmedMessages()").that(got).containsAtLeastElementsIn(expectedLines).inOrder(); 65 1 : } 66 : 67 : private String getTrimmedMessages() { 68 1 : return trimMessages(pushResult.getMessages()); 69 : } 70 : 71 : @VisibleForTesting 72 : @Nullable 73 : static String trimMessages(@Nullable String msg) { 74 2 : if (msg == null) { 75 1 : return null; 76 : } 77 2 : int idx = msg.indexOf("Processing changes:"); 78 2 : if (idx >= 0) { 79 2 : msg = msg.substring(0, idx); 80 : } 81 2 : return msg.trim(); 82 : } 83 : 84 : public void hasProcessed(ImmutableMap<String, Integer> expected) { 85 1 : isNotNull(); 86 : ImmutableMap<String, Integer> actual; 87 1 : String messages = pushResult.getMessages(); 88 : try { 89 1 : actual = parseProcessed(messages); 90 0 : } catch (RuntimeException e) { 91 0 : failWithActual( 92 0 : fact( 93 : "failed to parse \"Processing changes\" line from messages, reason:", 94 0 : Throwables.getStackTraceAsString(e))); 95 0 : return; 96 1 : } 97 1 : check("processedCommands()").that(actual).containsExactlyEntriesIn(expected).inOrder(); 98 1 : } 99 : 100 : @VisibleForTesting 101 : static ImmutableMap<String, Integer> parseProcessed(@Nullable String messages) { 102 2 : if (messages == null) { 103 1 : return ImmutableMap.of(); 104 : } 105 2 : String toSplit = messages.trim(); 106 2 : String prefix = "Processing changes: "; 107 2 : int idx = toSplit.lastIndexOf(prefix); 108 2 : if (idx < 0) { 109 1 : return ImmutableMap.of(); 110 : } 111 2 : toSplit = toSplit.substring(idx + prefix.length()); 112 2 : if (toSplit.equals("done")) { 113 1 : return ImmutableMap.of(); 114 : } 115 2 : String done = ", done"; 116 2 : if (toSplit.endsWith(done)) { 117 2 : toSplit = toSplit.substring(0, toSplit.length() - done.length()); 118 : } 119 2 : return ImmutableMap.copyOf( 120 2 : Maps.transformValues( 121 2 : Splitter.on(',').trimResults().withKeyValueSeparator(':').split(toSplit), 122 : // trimResults() doesn't trim values in the map. 123 2 : v -> Integer.parseInt(v.trim()))); 124 : } 125 : 126 : public RemoteRefUpdateSubject ref(String refName) { 127 1 : isNotNull(); 128 1 : return check("getRemoteUpdate(%s)", refName) 129 1 : .about(refs()) 130 1 : .that(pushResult.getRemoteUpdate(refName)); 131 : } 132 : 133 : public RemoteRefUpdateSubject onlyRef(String refName) { 134 1 : isNotNull(); 135 1 : check("setOfRefs()") 136 1 : .about(StreamSubject.streams()) 137 1 : .that(pushResult.getRemoteUpdates().stream().map(RemoteRefUpdate::getRemoteName)) 138 1 : .containsExactly(refName); 139 1 : return ref(refName); 140 : } 141 : 142 : public static class RemoteRefUpdateSubject extends Subject { 143 : private final RemoteRefUpdate remoteRefUpdate; 144 : 145 : private RemoteRefUpdateSubject(FailureMetadata metadata, RemoteRefUpdate remoteRefUpdate) { 146 1 : super(metadata, remoteRefUpdate); 147 1 : this.remoteRefUpdate = remoteRefUpdate; 148 1 : } 149 : 150 : static Factory<RemoteRefUpdateSubject, RemoteRefUpdate> refs() { 151 1 : return RemoteRefUpdateSubject::new; 152 : } 153 : 154 : public void hasStatus(RemoteRefUpdate.Status status) { 155 1 : isNotNull(); 156 1 : RemoteRefUpdate u = remoteRefUpdate; 157 1 : check("getStatus()") 158 1 : .withMessage( 159 1 : "status message: %s", u.getMessage() != null ? ": " + u.getMessage() : "<emtpy>") 160 1 : .that(u.getStatus()) 161 1 : .isEqualTo(status); 162 1 : } 163 : 164 : public void hasNoMessage() { 165 0 : isNotNull(); 166 0 : check("getMessage()").that(remoteRefUpdate.getMessage()).isNull(); 167 0 : } 168 : 169 : public void hasMessage(String expected) { 170 1 : isNotNull(); 171 1 : check("getMessage()").that(remoteRefUpdate.getMessage()).isEqualTo(expected); 172 1 : } 173 : 174 : public void isOk() { 175 1 : isNotNull(); 176 1 : hasStatus(RemoteRefUpdate.Status.OK); 177 1 : } 178 : 179 : public void isRejected(String expectedMessage) { 180 1 : isNotNull(); 181 1 : hasStatus(RemoteRefUpdate.Status.REJECTED_OTHER_REASON); 182 1 : hasMessage(expectedMessage); 183 1 : } 184 : } 185 : }