/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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 org.onosproject.cluster;

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

import org.junit.Test;
import org.onlab.packet.IpAddress;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onosproject.core.Version;

/**
 * Unit tests for ClusterMetadataDiff.
 */
public class ClusterMetadataDiffTest {

    @Test
    public void testDiffNoChange() {
        PartitionId pid1 = PartitionId.from(1);
        NodeId nid1 = NodeId.nodeId("10.0.0.1");
        ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
        ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
        ClusterMetadataDiff diff = new ClusterMetadataDiff(md1, md1);
        assertTrue(diff.nodesAdded().isEmpty());
        assertTrue(diff.nodesRemoved().isEmpty());
        assertEquals(diff.partitionDiffs().size(), 1);
        assertEquals(diff.partitionDiffs().keySet(), Sets.newHashSet(pid1));
        PartitionDiff pdiff = diff.partitionDiffs().get(pid1);
        assertFalse(pdiff.hasChanged());
    }

    @Test
    public void testDiffForScaleUp() {
        PartitionId pid1 = PartitionId.from(1);
        NodeId nid1 = NodeId.nodeId("10.0.0.1");
        NodeId nid2 = NodeId.nodeId("10.0.0.2");
        ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
        ControllerNode n2 = new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
        Partition p12 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
        ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
        ClusterMetadata md12 = new ClusterMetadata("foo", ImmutableSet.of(n1, n2), ImmutableSet.of(p12));
        ClusterMetadataDiff diff = new ClusterMetadataDiff(md1, md12);
        assertEquals(diff.nodesAdded(), Sets.newHashSet(n2));
        assertTrue(diff.nodesRemoved().isEmpty());
        assertEquals(diff.partitionDiffs().size(), 1);
        assertEquals(diff.partitionDiffs().keySet(), Sets.newHashSet(pid1));
        PartitionDiff pdiff = diff.partitionDiffs().get(pid1);
        assertTrue(pdiff.hasChanged());
        assertFalse(pdiff.isAdded(nid1));
        assertTrue(pdiff.isAdded(nid2));
        assertFalse(pdiff.isRemoved(nid1));
        assertFalse(pdiff.isAdded(nid1));
    }

    @Test
    public void testDiffForScaleDown() {
        PartitionId pid1 = PartitionId.from(1);
        NodeId nid1 = NodeId.nodeId("10.0.0.1");
        NodeId nid2 = NodeId.nodeId("10.0.0.2");
        ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
        ControllerNode n2 = new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
        Partition p12 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
        ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
        ClusterMetadata md12 = new ClusterMetadata("foo", ImmutableSet.of(n1, n2), ImmutableSet.of(p12));
        ClusterMetadataDiff diff = new ClusterMetadataDiff(md12, md1);
        assertEquals(diff.nodesRemoved(), Sets.newHashSet(nid2));
        assertTrue(diff.nodesAdded().isEmpty());
        assertEquals(diff.partitionDiffs().size(), 1);
        assertEquals(diff.partitionDiffs().keySet(), Sets.newHashSet(pid1));
        PartitionDiff pdiff = diff.partitionDiffs().get(pid1);
        assertTrue(pdiff.hasChanged());
        assertTrue(pdiff.isRemoved(nid2));
        assertFalse(pdiff.isAdded(nid2));
        assertFalse(pdiff.isRemoved(nid1));
        assertFalse(pdiff.isAdded(nid1));
    }
}
