/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.distributed.internal.membership;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.distributed.internal.membership.gms.GMSMembershipView;
import org.apache.geode.distributed.internal.membership.gms.api.MemberIdentifier;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.test.junit.categories.MembershipTest;

@Category({MembershipTest.class})
public class MembershipViewJUnitTest {

  private List<MemberIdentifier> members;

  @Before
  public void initMembers() throws Exception {
    int numMembers = 10;
    members = new ArrayList<>(numMembers);
    for (int i = 0; i < numMembers; i++) {
      members.add(new InternalDistributedMember(SocketCreator.getLocalHost(), 1000 + i));
    }
    // view creator is a locator
    members.get(0).setVmKind(ClusterDistributionManager.LOCATOR_DM_TYPE);
    members.get(0).setVmViewId(0);
    members.get(0).setPreferredForCoordinator(true);

    // members who joined in view #1
    for (int i = 1; i < (numMembers - 1); i++) {
      members.get(i).setVmViewId(1);
      members.get(i).setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
      members.get(i).setPreferredForCoordinator(false);
    }

    // member joining in this view
    members.get(numMembers - 1).setVmViewId(2);
    members.get(numMembers - 1).getMemberData()
        .setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
  }

  private void setFailureDetectionPorts(GMSMembershipView view) {
    int numMembers = members.size();
    // use the membership port as the FD port so it's easy to figure out problems
    for (int i = 0; i < numMembers; i++) {
      view.setFailureDetectionPort(members.get(i), members.get(i).getMembershipPort());
    }
  }

  @Test
  public void testCreateView() throws Exception {
    int numMembers = members.size();
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, members);
    setFailureDetectionPorts(view);

    assertTrue(view.getCreator().equals(members.get(0)));
    assertEquals(2, view.getViewId());
    assertEquals(members, view.getMembers());
    assertEquals(0, view.getCrashedMembers().size());
    assertEquals(members.get(1), view.getLeadMember()); // a locator can't be lead member
    assertEquals(0, view.getShutdownMembers().size());
    assertEquals(1, view.getNewMembers().size());
    assertEquals(members.get(numMembers - 1), view.getNewMembers().iterator().next());
    assertEquals(members.get(0), view.getCoordinator());

    for (int i = 0; i < numMembers; i++) {
      MemberIdentifier mbr = members.get(i);
      assertEquals(mbr.getMembershipPort(), view.getFailureDetectionPort(mbr));
    }

    assertFalse(view.shouldBeCoordinator(members.get(1)));
    assertTrue(view.shouldBeCoordinator(members.get(0)));
    assertEquals(members.get(numMembers - 1),
        view.getCoordinator(Collections.singletonList(members.get(0))));
    members.get(numMembers - 1).setPreferredForCoordinator(false);
    assertEquals(members.get(1), view.getCoordinator(Collections.singletonList(members.get(0))));

    members.get(numMembers - 1).setPreferredForCoordinator(true);
    List<MemberIdentifier> preferred = view.getPreferredCoordinators(
        Collections.<MemberIdentifier>singleton(members.get(1)), members.get(0), 2);
    assertEquals(2, preferred.size());
    assertEquals(members.get(numMembers - 1), preferred.get(0));
  }

  @Test
  public void testRemoveMembers() throws Exception {
    int numMembers = members.size();
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, new ArrayList<>(members));
    setFailureDetectionPorts(view);

    for (int i = 1; i < numMembers; i += 2) {
      view.remove(members.get(i));
      assertFalse(view.contains(members.get(i)));
    }

    List<MemberIdentifier> remainingMembers = view.getMembers();
    int num = remainingMembers.size();
    for (int i = 0; i < num; i++) {
      MemberIdentifier mbr = remainingMembers.get(i);
      assertEquals(mbr.getMembershipPort(), view.getFailureDetectionPort((MemberIdentifier) mbr));
    }
  }

  @Test
  public void testRemoveAll() throws Exception {
    int numMembers = members.size();
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, new ArrayList<>(members));
    setFailureDetectionPorts(view);

    Collection<MemberIdentifier> removals = new ArrayList<>(numMembers / 2);
    for (int i = 1; i < numMembers; i += 2) {
      removals.add(members.get(i));
    }

    view.removeAll(removals);
    for (MemberIdentifier mbr : removals) {
      assertFalse(view.contains(mbr));
    }
    assertEquals(numMembers - removals.size(), view.size());

    List<MemberIdentifier> remainingMembers = view.getMembers();
    int num = remainingMembers.size();
    for (int i = 0; i < num; i++) {
      MemberIdentifier mbr = remainingMembers.get(i);
      assertEquals(mbr.getMembershipPort(), view.getFailureDetectionPort((MemberIdentifier) mbr));
    }
  }

  @Test
  public void testCopyView() throws Exception {
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, new ArrayList<>(members));
    setFailureDetectionPorts(view);

    GMSMembershipView newView = new GMSMembershipView(view, 3);

    assertTrue(newView.getCreator().equals(members.get(0)));
    assertEquals(3, newView.getViewId());
    assertEquals(members, newView.getMembers());
    assertEquals(0, newView.getCrashedMembers().size());
    assertEquals(members.get(1), newView.getLeadMember()); // a locator can't be lead member
    assertEquals(0, newView.getShutdownMembers().size());
    assertEquals(0, newView.getNewMembers().size());
    assertTrue(newView.equals(view));
    assertTrue(view.equals(newView));
    newView.remove(members.get(1));
    assertFalse(newView.equals(view));
  }

  @Test
  public void testAddLotsOfMembers() throws Exception {
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, new ArrayList<>(members));
    setFailureDetectionPorts(view);

    GMSMembershipView copy = new GMSMembershipView(view, 2);

    int oldSize = view.size();
    for (int i = 0; i < 100; i++) {
      MemberIdentifier mbr = new InternalDistributedMember(SocketCreator.getLocalHost(), 2000 + i);
      mbr.setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
      mbr.setVmViewId(2);
      view.add(mbr);
      view.setFailureDetectionPort(mbr, 2000 + i);
    }

    assertEquals(oldSize + 100, view.size());
    for (MemberIdentifier mbr : view.getMembers()) {
      assertEquals(mbr.getMembershipPort(), view.getFailureDetectionPort(mbr));
    }

    assertEquals(100, view.getNewMembers(copy).size());
  }

  @Test
  public void testNullPublicKeysNotRetained() throws Exception {
    GMSMembershipView view = new GMSMembershipView(members.get(0), 2, new ArrayList<>(members));
    setFailureDetectionPorts(view);

    GMSMembershipView newView = new GMSMembershipView(view, 3);
    for (MemberIdentifier member : view.getMembers()) {
      view.setPublicKey((MemberIdentifier) member, null);
    }
    newView.setPublicKeys(view);
    for (MemberIdentifier member : view.getMembers()) {
      assertNull(newView.getPublicKey((MemberIdentifier) member));
      assertNull(view.getPublicKey((MemberIdentifier) member));
    }
  }

  /**
   * Test that failed weight calculations are correctly performed. See bug #47342
   */
  @Test
  public void testFailedWeight() throws Exception {
    // in #47342 a new view was created that contained a member that was joining but
    // was no longer reachable. The member was included in the failed-weight and not
    // in the previous view-weight, causing a spurious network partition to be declared
    MemberIdentifier members[] =
        new MemberIdentifier[] {
            new InternalDistributedMember("localhost", 1),
            new InternalDistributedMember("localhost", 2),
            new InternalDistributedMember("localhost", 3),
            new InternalDistributedMember("localhost", 4),
            new InternalDistributedMember("localhost", 5),
            new InternalDistributedMember("localhost", 6)};
    int i = 0;
    // weight 3
    members[i].setVmKind(ClusterDistributionManager.LOCATOR_DM_TYPE);
    members[i++].setPreferredForCoordinator(true);
    // weight 3
    members[i].setVmKind(ClusterDistributionManager.LOCATOR_DM_TYPE);
    members[i++].setPreferredForCoordinator(true);
    // weight 15 (cache+leader)
    members[i].setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
    members[i++].setPreferredForCoordinator(false);
    // weight 0
    members[i].setVmKind(ClusterDistributionManager.ADMIN_ONLY_DM_TYPE);
    members[i++].setPreferredForCoordinator(false);
    // weight 0
    members[i].setVmKind(ClusterDistributionManager.ADMIN_ONLY_DM_TYPE);
    members[i++].setPreferredForCoordinator(false);
    // weight 10
    members[i].setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
    members[i++].setPreferredForCoordinator(false);

    List<MemberIdentifier> vmbrs = new ArrayList<>(members.length);
    for (i = 0; i < members.length; i++) {
      vmbrs.add(members[i]);
    }
    GMSMembershipView lastView =
        new GMSMembershipView((MemberIdentifier) members[0], 4,
            (List<MemberIdentifier>) (List<?>) vmbrs);
    MemberIdentifier leader = (MemberIdentifier) members[2];
    assertTrue(!leader.preferredForCoordinator());

    MemberIdentifier joiningMember = new InternalDistributedMember("localhost", 7);
    joiningMember.setVmKind(ClusterDistributionManager.NORMAL_DM_TYPE);
    joiningMember.setPreferredForCoordinator(false);

    // have the joining member and another cache process (weight 10) in the failed members
    // collection and check to make sure that the joining member is not included in failed
    // weight calcs.
    Set<MemberIdentifier> failedMembers = new HashSet<>(3);
    failedMembers.add(joiningMember);
    failedMembers.add(members[members.length - 1]); // cache
    failedMembers.add(members[members.length - 2]); // admin
    List<MemberIdentifier> newMbrs =
        new ArrayList<>(lastView.getGMSMembers());
    newMbrs.removeAll(failedMembers);
    GMSMembershipView newView =
        new GMSMembershipView(members[0], 5, (List<MemberIdentifier>) (List<?>) newMbrs,
            Collections.emptySet(), (Set<MemberIdentifier>) (Set<?>) failedMembers);

    int failedWeight = newView.getCrashedMemberWeight(lastView);
    // System.out.println("last view = " + lastView);
    // System.out.println("failed mbrs = " + failedMembers);
    // System.out.println("failed weight = " + failedWeight);
    assertEquals("failure weight calculation is incorrect", 10, failedWeight);
    Set<MemberIdentifier> actual = newView.getActualCrashedMembers(lastView);
    assertTrue(!actual.contains(members[members.length - 2]));
  }
}
