blob: 2031bde7c0e841f6d295c9c2adbf8c23412a8134 [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.acceptance.testsuite.change;
import com.google.auto.value.AutoValue;
import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
import com.google.gerrit.acceptance.testsuite.change.TestRange.Position;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.Patch;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Optional;
/**
* Attributes of the human comment. If not provided, arbitrary values will be used. This class is
* very similar to {@link TestRobotCommentCreation} to allow separation between robot and human
* comments.
*/
@AutoValue
public abstract class TestCommentCreation {
public abstract Optional<String> message();
public abstract Optional<String> file();
public abstract Optional<Integer> line();
public abstract Optional<TestRange> range();
public abstract Optional<CommentSide> side();
public abstract Optional<Boolean> unresolved();
public abstract Optional<String> parentUuid();
public abstract Optional<String> tag();
public abstract Optional<Account.Id> author();
public abstract Optional<Instant> createdOn();
abstract Comment.Status status();
abstract ThrowingFunction<TestCommentCreation, String> commentCreator();
public static Builder builder(
ThrowingFunction<TestCommentCreation, String> commentCreator, Comment.Status commentStatus) {
return new AutoValue_TestCommentCreation.Builder()
.commentCreator(commentCreator)
.status(commentStatus);
}
@AutoValue.Builder
public abstract static class Builder {
public Builder noMessage() {
return message("");
}
/** Message text of the comment. */
public abstract Builder message(String message);
/** Indicates a patchset-level comment. */
public Builder onPatchsetLevel() {
return file(Patch.PATCHSET_LEVEL);
}
/** Indicates a file comment. The comment will be on the specified file. */
public Builder onFileLevelOf(String filePath) {
return file(filePath).line(null).range(null);
}
/**
* Starts the fluent change to create a line comment. The line comment will be at the indicated
* line. Lines start with 1.
*/
public FileBuilder<Builder> onLine(int line) {
return new FileBuilder<>(file -> file(file).line(line).range(null));
}
/**
* Starts the fluent chain to create a range comment. The range begins at the specified line.
* Lines start at 1. The start position (line, charOffset) is inclusive, the end position (line,
* charOffset) is exclusive.
*/
public PositionBuilder<StartAwarePositionBuilder<Builder>> fromLine(int startLine) {
return new PositionBuilder<>(
startCharOffset -> {
Position start = Position.builder().line(startLine).charOffset(startCharOffset).build();
TestRange.Builder testRangeBuilder = TestRange.builder().setStart(start);
return new StartAwarePositionBuilder<>(testRangeBuilder, this::range, this::file);
});
}
/** File on which the comment should be added. */
abstract Builder file(String filePath);
/** Line on which the comment should be added. */
abstract Builder line(@Nullable Integer line);
/** Range on which the comment should be added. */
abstract Builder range(@Nullable TestRange range);
/**
* Indicates that the comment refers to a file, line, range, ... in the commit of the patchset.
*
* <p>On the UI, such comments are shown on the right side of a diff view when a diff against
* base is selected. See {@link #onParentCommit()} for comments shown on the left side.
*/
public Builder onPatchsetCommit() {
return side(CommentSide.PATCHSET_COMMIT);
}
/**
* Indicates that the comment refers to a file, line, range, ... in the parent commit of the
* patchset.
*
* <p>On the UI, such comments are shown on the left side of a diff view when a diff against
* base is selected. See {@link #onPatchsetCommit()} for comments shown on the right side.
*
* <p>For merge commits, this indicates the first parent commit.
*/
public Builder onParentCommit() {
return side(CommentSide.PARENT_COMMIT);
}
/** Like {@link #onParentCommit()} but for the second parent of a merge commit. */
public Builder onSecondParentCommit() {
return side(CommentSide.SECOND_PARENT_COMMIT);
}
/**
* Like {@link #onParentCommit()} but for the AutoMerge commit created from the parents of a
* merge commit.
*/
public Builder onAutoMergeCommit() {
return side(CommentSide.AUTO_MERGE_COMMIT);
}
abstract Builder side(CommentSide side);
/** Indicates a resolved comment. */
public Builder resolved() {
return unresolved(false);
}
/** Indicates an unresolved comment. */
public Builder unresolved() {
return unresolved(true);
}
abstract Builder unresolved(boolean unresolved);
/**
* UUID of another comment to which this comment is a reply. This comment must have similar
* attributes (e.g. file, line, side) as the parent comment. The parent comment must be a
* published comment.
*/
public abstract Builder parentUuid(String parentUuid);
/** Tag to attach to the comment. */
public abstract Builder tag(String value);
/** Author of the comment. Must be an existing user account. */
public abstract Builder author(Account.Id accountId);
/**
* Creation time of the comment. Like {@link #createdOn(Instant)} but with an arbitrary, fixed
* time zone (-> deterministic test execution).
*/
public Builder createdOn(LocalDateTime createdOn) {
// We don't care about the exact time zone in most tests, just that it's fixed so that tests
// are deterministic.
return createdOn(createdOn.atZone(ZoneOffset.UTC).toInstant());
}
/**
* Creation time of the comment. This may also lie in the past or future. Comments stored in
* NoteDb support only second precision.
*/
public abstract Builder createdOn(Instant createdOn);
/**
* Status of the comment. Hidden in the API surface. Use {@link
* PerPatchsetOperations#newComment()} or {@link PerPatchsetOperations#newDraftComment()}
* depending on which type of comment you want to create.
*/
abstract Builder status(Comment.Status value);
abstract Builder commentCreator(ThrowingFunction<TestCommentCreation, String> commentCreator);
abstract TestCommentCreation autoBuild();
/**
* Creates the comment.
*
* @return the UUID of the created comment
*/
public String create() {
TestCommentCreation commentCreation = autoBuild();
return commentCreation.commentCreator().applyAndThrowSilently(commentCreation);
}
}
}