Line data Source code
1 : // Copyright (C) 2020 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.acceptance.testsuite.change; 16 : 17 : import com.google.auto.value.AutoValue; 18 : import com.google.gerrit.acceptance.testsuite.ThrowingFunction; 19 : import com.google.gerrit.acceptance.testsuite.change.TestRange.Position; 20 : import com.google.gerrit.common.Nullable; 21 : import com.google.gerrit.entities.Account; 22 : import com.google.gerrit.entities.Comment; 23 : import com.google.gerrit.entities.Patch; 24 : import java.time.Instant; 25 : import java.time.LocalDateTime; 26 : import java.time.ZoneOffset; 27 : import java.util.Optional; 28 : 29 : /** 30 : * Attributes of the human comment. If not provided, arbitrary values will be used. This class is 31 : * very similar to {@link TestRobotCommentCreation} to allow separation between robot and human 32 : * comments. 33 : */ 34 : @AutoValue 35 5 : public abstract class TestCommentCreation { 36 : 37 : public abstract Optional<String> message(); 38 : 39 : public abstract Optional<String> file(); 40 : 41 : public abstract Optional<Integer> line(); 42 : 43 : public abstract Optional<TestRange> range(); 44 : 45 : public abstract Optional<CommentSide> side(); 46 : 47 : public abstract Optional<Boolean> unresolved(); 48 : 49 : public abstract Optional<String> parentUuid(); 50 : 51 : public abstract Optional<String> tag(); 52 : 53 : public abstract Optional<Account.Id> author(); 54 : 55 : public abstract Optional<Instant> createdOn(); 56 : 57 : abstract Comment.Status status(); 58 : 59 : abstract ThrowingFunction<TestCommentCreation, String> commentCreator(); 60 : 61 : public static Builder builder( 62 : ThrowingFunction<TestCommentCreation, String> commentCreator, Comment.Status commentStatus) { 63 5 : return new AutoValue_TestCommentCreation.Builder() 64 5 : .commentCreator(commentCreator) 65 5 : .status(commentStatus); 66 : } 67 : 68 : @AutoValue.Builder 69 5 : public abstract static class Builder { 70 : 71 : public Builder noMessage() { 72 1 : return message(""); 73 : } 74 : 75 : /** Message text of the comment. */ 76 : public abstract Builder message(String message); 77 : 78 : /** Indicates a patchset-level comment. */ 79 : public Builder onPatchsetLevel() { 80 2 : return file(Patch.PATCHSET_LEVEL); 81 : } 82 : 83 : /** Indicates a file comment. The comment will be on the specified file. */ 84 : public Builder onFileLevelOf(String filePath) { 85 2 : return file(filePath).line(null).range(null); 86 : } 87 : 88 : /** 89 : * Starts the fluent change to create a line comment. The line comment will be at the indicated 90 : * line. Lines start with 1. 91 : */ 92 : public FileBuilder<Builder> onLine(int line) { 93 2 : return new FileBuilder<>(file -> file(file).line(line).range(null)); 94 : } 95 : 96 : /** 97 : * Starts the fluent chain to create a range comment. The range begins at the specified line. 98 : * Lines start at 1. The start position (line, charOffset) is inclusive, the end position (line, 99 : * charOffset) is exclusive. 100 : */ 101 : public PositionBuilder<StartAwarePositionBuilder<Builder>> fromLine(int startLine) { 102 2 : return new PositionBuilder<>( 103 : startCharOffset -> { 104 2 : Position start = Position.builder().line(startLine).charOffset(startCharOffset).build(); 105 2 : TestRange.Builder testRangeBuilder = TestRange.builder().setStart(start); 106 2 : return new StartAwarePositionBuilder<>(testRangeBuilder, this::range, this::file); 107 : }); 108 : } 109 : 110 : /** File on which the comment should be added. */ 111 : abstract Builder file(String filePath); 112 : 113 : /** Line on which the comment should be added. */ 114 : abstract Builder line(@Nullable Integer line); 115 : 116 : /** Range on which the comment should be added. */ 117 : abstract Builder range(@Nullable TestRange range); 118 : 119 : /** 120 : * Indicates that the comment refers to a file, line, range, ... in the commit of the patchset. 121 : * 122 : * <p>On the UI, such comments are shown on the right side of a diff view when a diff against 123 : * base is selected. See {@link #onParentCommit()} for comments shown on the left side. 124 : */ 125 : public Builder onPatchsetCommit() { 126 1 : return side(CommentSide.PATCHSET_COMMIT); 127 : } 128 : 129 : /** 130 : * Indicates that the comment refers to a file, line, range, ... in the parent commit of the 131 : * patchset. 132 : * 133 : * <p>On the UI, such comments are shown on the left side of a diff view when a diff against 134 : * base is selected. See {@link #onPatchsetCommit()} for comments shown on the right side. 135 : * 136 : * <p>For merge commits, this indicates the first parent commit. 137 : */ 138 : public Builder onParentCommit() { 139 2 : return side(CommentSide.PARENT_COMMIT); 140 : } 141 : 142 : /** Like {@link #onParentCommit()} but for the second parent of a merge commit. */ 143 : public Builder onSecondParentCommit() { 144 2 : return side(CommentSide.SECOND_PARENT_COMMIT); 145 : } 146 : 147 : /** 148 : * Like {@link #onParentCommit()} but for the AutoMerge commit created from the parents of a 149 : * merge commit. 150 : */ 151 : public Builder onAutoMergeCommit() { 152 2 : return side(CommentSide.AUTO_MERGE_COMMIT); 153 : } 154 : 155 : abstract Builder side(CommentSide side); 156 : 157 : /** Indicates a resolved comment. */ 158 : public Builder resolved() { 159 2 : return unresolved(false); 160 : } 161 : 162 : /** Indicates an unresolved comment. */ 163 : public Builder unresolved() { 164 2 : return unresolved(true); 165 : } 166 : 167 : abstract Builder unresolved(boolean unresolved); 168 : 169 : /** 170 : * UUID of another comment to which this comment is a reply. This comment must have similar 171 : * attributes (e.g. file, line, side) as the parent comment. The parent comment must be a 172 : * published comment. 173 : */ 174 : public abstract Builder parentUuid(String parentUuid); 175 : 176 : /** Tag to attach to the comment. */ 177 : public abstract Builder tag(String value); 178 : 179 : /** Author of the comment. Must be an existing user account. */ 180 : public abstract Builder author(Account.Id accountId); 181 : 182 : /** 183 : * Creation time of the comment. Like {@link #createdOn(Instant)} but with an arbitrary, fixed 184 : * time zone (-> deterministic test execution). 185 : */ 186 : public Builder createdOn(LocalDateTime createdOn) { 187 : // We don't care about the exact time zone in most tests, just that it's fixed so that tests 188 : // are deterministic. 189 2 : return createdOn(createdOn.atZone(ZoneOffset.UTC).toInstant()); 190 : } 191 : 192 : /** 193 : * Creation time of the comment. This may also lie in the past or future. Comments stored in 194 : * NoteDb support only second precision. 195 : */ 196 : public abstract Builder createdOn(Instant createdOn); 197 : 198 : /** 199 : * Status of the comment. Hidden in the API surface. Use {@link 200 : * PerPatchsetOperations#newComment()} or {@link PerPatchsetOperations#newDraftComment()} 201 : * depending on which type of comment you want to create. 202 : */ 203 : abstract Builder status(Comment.Status value); 204 : 205 : abstract Builder commentCreator(ThrowingFunction<TestCommentCreation, String> commentCreator); 206 : 207 : abstract TestCommentCreation autoBuild(); 208 : 209 : /** 210 : * Creates the comment. 211 : * 212 : * @return the UUID of the created comment 213 : */ 214 : public String create() { 215 5 : TestCommentCreation commentCreation = autoBuild(); 216 5 : return commentCreation.commentCreator().applyAndThrowSilently(commentCreation); 217 : } 218 : } 219 : }