LCOV - code coverage report
Current view: top level - server/git/validators - CommentCumulativeSizeValidator.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 32 32 100.0 %
Date: 2022-11-19 15:00:39 Functions: 5 5 100.0 %

          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.server.git.validators;
      16             : 
      17             : import com.google.common.collect.ImmutableList;
      18             : import com.google.common.collect.Iterables;
      19             : import com.google.gerrit.entities.Change;
      20             : import com.google.gerrit.entities.Comment;
      21             : import com.google.gerrit.entities.Project;
      22             : import com.google.gerrit.extensions.validators.CommentForValidation;
      23             : import com.google.gerrit.extensions.validators.CommentValidationContext;
      24             : import com.google.gerrit.extensions.validators.CommentValidationFailure;
      25             : import com.google.gerrit.extensions.validators.CommentValidator;
      26             : import com.google.gerrit.server.config.GerritServerConfig;
      27             : import com.google.gerrit.server.notedb.ChangeNotes;
      28             : import com.google.inject.Inject;
      29             : import java.util.stream.Stream;
      30             : import org.eclipse.jgit.lib.Config;
      31             : 
      32             : /**
      33             :  * Limits the total size of all comments and change messages to prevent space/time complexity
      34             :  * issues. Note that autogenerated change messages are not subject to validation. However, we still
      35             :  * count autogenerated messages for the limit (which will be notified on a further comment).
      36             :  */
      37             : public class CommentCumulativeSizeValidator implements CommentValidator {
      38             :   public static final int DEFAULT_CUMULATIVE_COMMENT_SIZE_LIMIT = 3 << 20;
      39             : 
      40             :   private final int maxCumulativeSize;
      41             :   private final ChangeNotes.Factory notesFactory;
      42             : 
      43             :   @Inject
      44             :   CommentCumulativeSizeValidator(
      45          65 :       @GerritServerConfig Config serverConfig, ChangeNotes.Factory notesFactory) {
      46          65 :     this.notesFactory = notesFactory;
      47          65 :     maxCumulativeSize =
      48          65 :         serverConfig.getInt(
      49             :             "change", "cumulativeCommentSizeLimit", DEFAULT_CUMULATIVE_COMMENT_SIZE_LIMIT);
      50          65 :   }
      51             : 
      52             :   @Override
      53             :   public ImmutableList<CommentValidationFailure> validateComments(
      54             :       CommentValidationContext ctx, ImmutableList<CommentForValidation> comments) {
      55          65 :     ChangeNotes notes =
      56          65 :         notesFactory.createChecked(Project.nameKey(ctx.getProject()), Change.id(ctx.getChangeId()));
      57          65 :     int existingCumulativeSize =
      58          65 :         Stream.concat(
      59          65 :                     notes.getHumanComments().values().stream(),
      60          65 :                     notes.getRobotComments().values().stream())
      61          65 :                 .mapToInt(Comment::getApproximateSize)
      62          65 :                 .sum()
      63          65 :             + notes.getChangeMessages().stream().mapToInt(cm -> cm.getMessage().length()).sum();
      64          65 :     int newCumulativeSize =
      65          65 :         comments.stream().mapToInt(CommentForValidation::getApproximateSize).sum();
      66          65 :     ImmutableList.Builder<CommentValidationFailure> failures = ImmutableList.builder();
      67          65 :     if (!comments.isEmpty() && !isEnoughSpace(notes, newCumulativeSize, maxCumulativeSize)) {
      68             :       // This warning really applies to the set of all comments, but we need to pick one to attach
      69             :       // the message to.
      70           5 :       CommentForValidation commentForFailureMessage = Iterables.getLast(comments);
      71             : 
      72           5 :       failures.add(
      73           5 :           commentForFailureMessage.failValidation(
      74           5 :               String.format(
      75             :                   "Exceeding maximum cumulative size of comments and change messages:"
      76             :                       + " %d (existing) + %d (new) > %d",
      77           5 :                   existingCumulativeSize, newCumulativeSize, maxCumulativeSize)));
      78             :     }
      79          65 :     return failures.build();
      80             :   }
      81             : 
      82             :   /**
      83             :    * Returns {@code true} if there is available space and the new size that we wish to add is less
      84             :    * than the maximum allowed size. {@code false} otherwise (if there is not enough space).
      85             :    */
      86             :   public static boolean isEnoughSpace(ChangeNotes notes, int addedBytes, int maxCumulativeSize) {
      87          67 :     int existingCumulativeSize =
      88          67 :         Stream.concat(
      89          67 :                     notes.getHumanComments().values().stream(),
      90          67 :                     notes.getRobotComments().values().stream())
      91          67 :                 .mapToInt(Comment::getApproximateSize)
      92          67 :                 .sum()
      93          67 :             + notes.getChangeMessages().stream().mapToInt(cm -> cm.getMessage().length()).sum();
      94          67 :     return existingCumulativeSize + addedBytes < maxCumulativeSize;
      95             :   }
      96             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750