// Copyright (C) 2019 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.findowners;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestPlugin;
import org.junit.Rule;
import org.junit.Test;

/** Test find-owners plugin features related to inheritance and set noparent statements. */
@TestPlugin(name = "find-owners", sysModule = "com.googlesource.gerrit.plugins.findowners.Module")
public class InheritanceIT extends FindOwners {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  @Rule public Watcher watcher = new Watcher(logger);

  @Test
  public void includePerFileNoParentTest() throws Exception {
    // Test included file with per-file and set noparent, which affects the including file.
    PushOneCommit.Result c1 =
        addFile(
            "1", "d1/d1/OWNERS", "d1d1@g\nper-file OW* = set noparent\nper-file OWNERS=d1d1o@g\n");
    PushOneCommit.Result c2 =
        addFile("2", "d1/OWNERS", "d1@g\nper-file OWNERS=d1o@g\nper-file * = set noparent\n");
    PushOneCommit.Result c3 =
        addFile("3", "d2/d1/OWNERS", "per-file O*S=d2d1o@g\nd2d1@g\ninclude ../../d1/d1/OWNERS\n");
    PushOneCommit.Result c4 =
        addFile("4", "d2/OWNERS", "d2@g\nper-file OWNERS=d2o@g\nper-file *S=set  noparent \n");
    // Files that match per-file globs with set noparent do not inherit global default owners.
    // But include directive can include more per-file owners as in c3.
    assertThat(getOwnersResponse(c1)).contains("{ ./d1/d1/OWNERS:[ d1d1o@g ] }");
    assertThat(getOwnersResponse(c2)).contains("{ ./d1/OWNERS:[ d1o@g ] }");
    assertThat(getOwnersResponse(c3)).contains("{ ./d2/d1/OWNERS:[ d1d1o@g, d2d1o@g ] }");
    assertThat(getOwnersResponse(c4)).contains("{ ./d2/OWNERS:[ d2o@g ] }");
  }

  @Test
  public void includeNoParentTest() throws Exception {
    // Test included file with noparent, which affects the inheritance of including file.
    PushOneCommit.Result c1 = addFile("1", "d1/d1/OWNERS", "d1d1@g\nset noparent\n");
    PushOneCommit.Result c2 = addFile("2", "d1/d2/OWNERS", "d1d2@g\n");
    PushOneCommit.Result c3 = addFile("3", "d1/OWNERS", "d1@g\n");
    PushOneCommit.Result c4 = addFile("4", "d2/d1/OWNERS", "d2d1@g\ninclude ../../d1/d1/OWNERS\n");
    PushOneCommit.Result c5 = addFile("5", "d2/d2/OWNERS", "d2d2@g\ninclude ../../d1/d2/OWNERS");
    PushOneCommit.Result c6 = addFile("6", "d2/OWNERS", "d2@g\n");
    // d1/d1/OWNERS sets noparent, does not inherit d1/OWNERS
    assertThat(getOwnersResponse(c1)).contains("{ ./d1/d1/OWNERS:[ d1d1@g ] }");
    // d1/d2/OWNERS inherits d1/OWNERS
    assertThat(getOwnersResponse(c2)).contains("{ ./d1/d2/OWNERS:[ d1@g, d1d2@g ] }");
    assertThat(getOwnersResponse(c3)).contains("{ ./d1/OWNERS:[ d1@g ] }");
    // d2/d1/OWNERS includes d1/d1/OWNERS, does not inherit d1/OWNERS or d2/OWNERS
    assertThat(getOwnersResponse(c4)).contains("{ ./d2/d1/OWNERS:[ d1d1@g, d2d1@g ] }");
    // d2/d2/OWNERS includes d1/d1/OWNERS, inherit d2/OWNERS but not d1/OWNERS
    assertThat(getOwnersResponse(c5)).contains("{ ./d2/d2/OWNERS:[ d1d2@g, d2@g, d2d2@g ] }");
    assertThat(getOwnersResponse(c6)).contains("{ ./d2/OWNERS:[ d2@g ] }");
  }

  @Test
  public void subOwnersFileTest() throws Exception {
    // Add OWNERS file in root and subdirectories.
    addFile("1", "OWNERS", "x@x\n");
    addFile("2", "d1/OWNERS", "a@a\n");
    addFile("3", "d2/OWNERS", "y@y\n");
    addFile("4", "d3/OWNERS", "b@b\nset noparent\n");
    addFile("5", "d4/OWNERS", "z@z\ninclude ../d2/OWNERS");
    // Add "t.c" file, which is not owned by subdirectory owners.
    PushOneCommit.Result c2 = createChange("c2", "t.c", "Hello!");
    String ownerA = ownerJson("a@a");
    String ownerX = ownerJson("x@x");
    assertThat(getOwnersResponse(c2)).contains("owners:[ " + ownerX + " ], files:[ t.c ]");
    // Add "d1/t.c" file, which is owned by ./d1 and root owners.
    PushOneCommit.Result c3 = createChange("c3", "d1/t.c", "Hello!");
    String ownerX010 = ownerJson("x@x", 0, 1, 0);
    assertThat(getOwnersResponse(c3))
        .contains("owners:[ " + ownerA + ", " + ownerX010 + " ], files:[ d1/t.c ]");
    // Add "d2/t.c" file, which is owned by ./d2 and root owners.
    PushOneCommit.Result c4 = createChange("c4", "d2/t.c", "Hello!");
    String ownerY = ownerJson("y@y");
    assertThat(getOwnersResponse(c4))
        .contains("owners:[ " + ownerY + ", " + ownerX010 + " ], files:[ d2/t.c ]");
    // Add "d2/d1/t.c" file, which is owned by ./d2 and root owners.
    PushOneCommit.Result c5 = createChange("c5", "d2/d1/t.c", "Hello!");
    assertThat(getOwnersResponse(c5))
        .contains("owners:[ " + ownerY + ", " + ownerX010 + " ], files:[ d2/d1/t.c ]");
    // Add "d3/t.c" file, which is owned only by ./d3 owners due to "set noparent".
    PushOneCommit.Result c6 = createChange("c6", "d3/t.c", "Hello!");
    String ownerB = ownerJson("b@b");
    assertThat(getOwnersResponse(c6)).contains("owners:[ " + ownerB + " ], files:[ d3/t.c ]");
    // Add "d3/d1/t.c" file, which is owned only by ./d3 owners due to "set noparent".
    PushOneCommit.Result c7 = createChange("c7", "d3/d1/t.c", "Hello!");
    assertThat(getOwnersResponse(c7)).contains("owners:[ " + ownerB + " ], files:[ d3/d1/t.c ]");
    // Add "d4/t.c" file, which is owned by ./d4 and ./d2 owners, but not root owners.
    PushOneCommit.Result c8 = createChange("c8", "d4/t.c", "Hello!");
    String ownerZ = ownerJson("z@z");
    assertThat(getOwnersResponse(c8))
        .contains("owners:[ " + ownerY + ", " + ownerZ + ", " + ownerX010 + " ], files:[ d4/t.c ]");
  }
}
