/*
 * Copyright 2014 Open Networking Laboratory
 *
 * 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.net.flow;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.junit.Test;

import com.google.common.testing.EqualsTester;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass;

/**
 * Unit tests for the BatchOperationTest object.
 */
public class BatchOperationTest {

    private enum TestType {
        OP1,
        OP2,
        OP3
    }

    final TestEntry entry1 = new TestEntry(TestType.OP1, new TestTarget(1));
    final TestEntry entry2 = new TestEntry(TestType.OP2, new TestTarget(2));


    private static final class TestTarget implements BatchOperationTarget {
        private int id;

        private TestTarget(int id) {
            this.id = id;
        }

        @Override
        public int hashCode() {
            return id;
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }

            if (o == null) {
                return false;
            }

            if (getClass() != o.getClass()) {
                return false;
            }
            TestTarget that = (TestTarget) o;
            return this.id == that.id;
        }

    }

    private static final class TestEntry extends BatchOperationEntry<TestType, TestTarget> {
        public TestEntry(TestType operator, TestTarget target) {
            super(operator, target);
        }
    }

    private static final class TestOperation extends BatchOperation<TestEntry> {
        private TestOperation() {
            super();
        }

        private TestOperation(Collection<TestEntry> batchOperations) {
            super(batchOperations);
        }
    }

    /**
     * Checks that the DefaultFlowRule class is immutable.
     */
    @Test
    public void testImmutability() {
        assertThatClassIsImmutableBaseClass(BatchOperation.class);
    }

    /**
     * Tests the equals(), hashCode() and toString() operations.
     */
    @Test
    public void testEquals() {
        final List<TestEntry> ops1 = new LinkedList<>();
        ops1.add(entry1);
        final List<TestEntry> ops2 = new LinkedList<>();
        ops2.add(entry2);

        final TestOperation op1 = new TestOperation(ops1);
        final TestOperation sameAsOp1 = new TestOperation(ops1);
        final TestOperation op2 = new TestOperation(ops2);

        new EqualsTester()
                .addEqualityGroup(op1, sameAsOp1)
                .addEqualityGroup(op2)
                .testEquals();
    }

    /**
     * Tests the constructors for a BatchOperation.
     */
    @Test
    public void testConstruction() {
        final List<TestEntry> ops = new LinkedList<>();
        ops.add(entry2);

        final TestOperation op1 = new TestOperation();
        assertThat(op1.size(), is(0));
        assertThat(op1.getOperations(), hasSize(0));

        final TestOperation op2 = new TestOperation(ops);
        op1.addOperation(entry1);
        op1.addAll(op2);
        assertThat(op1.size(), is(2));
        assertThat(op1.getOperations(), hasSize(2));

        op2.clear();
        assertThat(op2.size(), is(0));
        assertThat(op2.getOperations(), hasSize(0));
    }

    /**
     * Tests the constructor for BatchOperationEntries.
     */
    @Test
    public void testEntryConstruction() {
        final TestEntry entry = new TestEntry(TestType.OP3, new TestTarget(3));

        assertThat(entry.getOperator(), is(TestType.OP3));
        assertThat(entry.getTarget().id, is(3));
    }
}
