// Copyright (C) 2017 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.googlesource.gerrit.plugins.uploadvalidator;

import static com.google.common.truth.Truth.assertThat;
import static com.googlesource.gerrit.plugins.uploadvalidator.TestUtils.EMPTY_PLUGIN_CONFIG;

import com.google.common.collect.Lists;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoFilepatternException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Test;

public class FileExtensionValidatorTest extends ValidatorTestCase {
  private static final List<String> BLOCKED_EXTENSIONS_LC =
      Lists.newArrayList("jpeg", "pdf", "zip", "exe", "tar.gz");
  private static final List<String> BLOCKED_EXTENSIONS_UC =
      Lists.newArrayList("JPEG", "PDF", "ZIP", "EXE", "TAR.GZ");

  private RevCommit makeCommit(RevWalk rw, List<String> blockedExtensions)
      throws NoFilepatternException, IOException, GitAPIException {
    Set<File> files = new HashSet<>();
    for (String extension : blockedExtensions) {
      files.add(new File(repo.getDirectory().getParent(), "foo." + extension));
    }
    // valid extensions
    files.add(new File(repo.getDirectory().getParent(), "foo.java"));
    files.add(new File(repo.getDirectory().getParent(), "foo.core.tmp"));
    files.add(new File(repo.getDirectory().getParent(), "foo.c"));
    files.add(new File(repo.getDirectory().getParent(), "foo.txt"));
    return TestUtils.makeCommit(rw, repo, "Commit with empty test files.", files);
  }

  @Test
  public void testBlockedExtensions() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, BLOCKED_EXTENSIONS_LC);
      List<CommitValidationMessage> m =
          FileExtensionValidator.performValidation(repo, c, rw, BLOCKED_EXTENSIONS_LC);
      List<String> expected = new ArrayList<>();
      for (String extension : BLOCKED_EXTENSIONS_LC) {
        expected.add("ERROR: blocked file: foo." + extension);
      }
      assertThat(TestUtils.transformMessages(m)).containsExactlyElementsIn(expected);
    }
  }

  @Test
  public void testBlockedExtensionsCaseInsensitive() throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      RevCommit c = makeCommit(rw, BLOCKED_EXTENSIONS_UC);
      List<CommitValidationMessage> m =
          FileExtensionValidator.performValidation(repo, c, rw, BLOCKED_EXTENSIONS_LC);
      List<String> expected = new ArrayList<>();
      for (String extension : BLOCKED_EXTENSIONS_UC) {
        expected.add("ERROR: blocked file: foo." + extension);
      }
      assertThat(TestUtils.transformMessages(m)).containsExactlyElementsIn(expected);
    }
  }

  @Test
  public void validatorInactiveWhenConfigEmpty() {
    assertThat(FileExtensionValidator.isActive(EMPTY_PLUGIN_CONFIG)).isFalse();
  }
}
