// Copyright (C) 2016 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 static com.googlesource.gerrit.plugins.uploadvalidator.TestUtils.PATTERN_CACHE;

import com.google.gerrit.server.git.validators.CommitValidationMessage;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ContentTypeValidatorTest extends ValidatorTestCase {

  private static final byte[] TEST_PDF =
      ("%PDF-1.4\n"
              + "1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 3 0 R >>\n"
              + "endobj 2 0 obj << /Type /Outlines /Count 0 >>\n"
              + "endobj 3 0 obj << /Type /Pages /Kids [4 0 R] /Count 1\n"
              + ">> endobj 4 0 obj << /Type /Page /Parent 3 0 R\n"
              + "/MediaBox [0 0 612 144] /Contents 5 0 R /Resources << /ProcSet 6 0 R\n"
              + "/Font << /F1 7 0 R >> >> >> endobj 5 0 obj\n"
              + "<< /Length 73 >> stream BT\n"
              + "/F1 24 Tf\n"
              + "100 100 Td\n"
              + "(Small pdf) Tj\n"
              + "ET endstream endobj 6 0 obj [/PDF /Text] endobj 7 0 obj\n"
              + "<< /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica\n"
              + "/Encoding /MacRomanEncoding >> endobj xref 0 8\n"
              + "0000000000 65535 f 0000000009 00000 n 0000000074 00000 n\n"
              + "0000000120 00000 n 0000000179 00000 n 0000000364 00000 n\n"
              + "0000000466 00000 n 0000000496 00000 n\n"
              + "trailer << /Size 8 /Root 1 0 R >> startxref 625\n"
              + "%%EOF")
          .getBytes(StandardCharsets.UTF_8);

  private ContentTypeValidator validator;

  @Before
  public void setUp() {
    validator =
        new ContentTypeValidator(null, new ContentTypeUtil(PATTERN_CACHE), null, null, null);
  }

  @Test
  public void testBlocked() throws Exception {
    String[] patterns = new String[] {"application/pdf", "application/xml", "text/html"};

    try (RevWalk rw = new RevWalk(repo)) {
      List<CommitValidationMessage> m =
          validator.performValidation(repo, makeCommit(rw), rw, patterns, false);
      assertThat(TestUtils.transformMessages(m))
          .containsExactly(
              "ERROR: found blocked content type (application/pdf) in file: foo.pdf",
              "ERROR: found blocked content type (application/xml) in file: foo.xml",
              "ERROR: found blocked content type (text/html) in file: foo.html");
    }
  }

  @Test
  public void testWhitelist() throws Exception {
    String[] patterns = new String[] {"application/pdf", "application/xml"};

    try (RevWalk rw = new RevWalk(repo)) {
      List<CommitValidationMessage> m =
          validator.performValidation(repo, makeCommit(rw), rw, patterns, true);
      assertThat(TestUtils.transformMessages(m))
          .containsExactly("ERROR: found blocked content type (text/html) in file: foo.html");
    }
  }

  @Test
  public void validatorBehaviorWhenConfigEmpty() {
    assertThat(ContentTypeValidator.isActive(EMPTY_PLUGIN_CONFIG)).isFalse();
    assertThat(ContentTypeValidator.isWhitelist(EMPTY_PLUGIN_CONFIG)).isFalse();
  }

  private RevCommit makeCommit(RevWalk rw) throws IOException, GitAPIException {
    Map<File, byte[]> files = new HashMap<>();

    String content = "<?xml version=\"1.0\"?><a><b>c</b></a>";
    files.put(TestUtils.createEmptyFile("foo.xml", repo), content.getBytes(StandardCharsets.UTF_8));

    content = "<html><body><h1>Hello World!</h1></body></html>";
    files.put(
        TestUtils.createEmptyFile("foo.html", repo), content.getBytes(StandardCharsets.UTF_8));

    files.put(TestUtils.createEmptyFile("foo.pdf", repo), TEST_PDF);
    return TestUtils.makeCommit(rw, repo, "Commit with test files.", files);
  }
}
