// Copyright (C) 2018 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.server.permissions;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
import org.junit.Test;

public class PermissionBackendConditionIT extends AbstractDaemonTest {

  @Inject PermissionBackend pb;

  @Test
  public void globalPermissions_sameUserAndPermissionEquals() throws Exception {
    BooleanCondition cond1 = pb.user(user()).testCond(GlobalPermission.CREATE_GROUP);
    BooleanCondition cond2 = pb.user(user()).testCond(GlobalPermission.CREATE_GROUP);
    assertEquals(cond1, cond2);
    assertEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void globalPermissions_differentPermissionDoesNotEquals() throws Exception {
    BooleanCondition cond1 = pb.user(user()).testCond(GlobalPermission.CREATE_GROUP);
    BooleanCondition cond2 = pb.user(user()).testCond(GlobalPermission.ACCESS_DATABASE);
    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void globalPermissions_differentUserDoesNotEqual() throws Exception {
    BooleanCondition cond1 = pb.user(user()).testCond(GlobalPermission.CREATE_GROUP);
    BooleanCondition cond2 = pb.user(admin()).testCond(GlobalPermission.CREATE_GROUP);
    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void changePermissions_sameResourceAndUserEquals() throws Exception {
    ChangeData change = createChange().getChange();
    BooleanCondition cond1 = pb.user(user()).change(change).testCond(ChangePermission.READ);
    BooleanCondition cond2 = pb.user(user()).change(change).testCond(ChangePermission.READ);

    assertEquals(cond1, cond2);
    assertEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void changePermissions_sameResourceDifferentUserDoesNotEqual() throws Exception {
    ChangeData change = createChange().getChange();
    BooleanCondition cond1 = pb.user(user()).change(change).testCond(ChangePermission.READ);
    BooleanCondition cond2 = pb.user(admin()).change(change).testCond(ChangePermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void changePermissions_differentResourceSameUserDoesNotEqual() throws Exception {
    ChangeData change1 = createChange().getChange();
    ChangeData change2 = createChange().getChange();
    BooleanCondition cond1 = pb.user(user()).change(change1).testCond(ChangePermission.READ);
    BooleanCondition cond2 = pb.user(user()).change(change2).testCond(ChangePermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void projectPermissions_sameResourceAndUserEquals() throws Exception {
    BooleanCondition cond1 = pb.user(user()).project(project).testCond(ProjectPermission.READ);
    BooleanCondition cond2 = pb.user(user()).project(project).testCond(ProjectPermission.READ);

    assertEquals(cond1, cond2);
    assertEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void projectPermissions_sameResourceDifferentUserDoesNotEqual() throws Exception {
    BooleanCondition cond1 = pb.user(user()).project(project).testCond(ProjectPermission.READ);
    BooleanCondition cond2 = pb.user(admin()).project(project).testCond(ProjectPermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void projectPermissions_differentResourceSameUserDoesNotEqual() throws Exception {
    Project.NameKey project2 = createProject("p2");
    BooleanCondition cond1 = pb.user(user()).project(project).testCond(ProjectPermission.READ);
    BooleanCondition cond2 = pb.user(user()).project(project2).testCond(ProjectPermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void refPermissions_sameResourceAndUserEquals() throws Exception {
    Branch.NameKey branch = new Branch.NameKey(project, "branch");
    BooleanCondition cond1 = pb.user(user()).ref(branch).testCond(RefPermission.READ);
    BooleanCondition cond2 = pb.user(user()).ref(branch).testCond(RefPermission.READ);

    assertEquals(cond1, cond2);
    assertEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void refPermissions_sameResourceAndDifferentUserDoesNotEqual() throws Exception {
    Branch.NameKey branch = new Branch.NameKey(project, "branch");
    BooleanCondition cond1 = pb.user(user()).ref(branch).testCond(RefPermission.READ);
    BooleanCondition cond2 = pb.user(admin()).ref(branch).testCond(RefPermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void refPermissions_differentResourceAndSameUserDoesNotEqual() throws Exception {
    Branch.NameKey branch1 = new Branch.NameKey(project, "branch");
    Branch.NameKey branch2 = new Branch.NameKey(project, "branch2");
    BooleanCondition cond1 = pb.user(user()).ref(branch1).testCond(RefPermission.READ);
    BooleanCondition cond2 = pb.user(user()).ref(branch2).testCond(RefPermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  @Test
  public void refPermissions_differentResourceAndSameUserDoesNotEqual2() throws Exception {
    Branch.NameKey branch1 = new Branch.NameKey(project, "branch");
    Branch.NameKey branch2 = new Branch.NameKey(createProject("p2"), "branch");
    BooleanCondition cond1 = pb.user(user()).ref(branch1).testCond(RefPermission.READ);
    BooleanCondition cond2 = pb.user(user()).ref(branch2).testCond(RefPermission.READ);

    assertNotEquals(cond1, cond2);
    assertNotEquals(cond1.hashCode(), cond2.hashCode());
  }

  private CurrentUser user() {
    return identifiedUserFactory.create(user.id);
  }

  private CurrentUser admin() {
    return identifiedUserFactory.create(admin.id);
  }
}
