/*
 * Copyright 2016 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.ospf.controller.area;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfAreaAddressRange;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfNbr;
import org.onosproject.ospf.controller.OspfNeighborState;
import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
import org.onosproject.ospf.controller.impl.Controller;
import org.onosproject.ospf.controller.impl.OspfInterfaceChannelHandler;
import org.onosproject.ospf.controller.impl.OspfNbrImpl;
import org.onosproject.ospf.controller.impl.TopologyForDeviceAndLinkImpl;
import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
import org.onosproject.ospf.protocol.util.OspfInterfaceState;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

/**
 * Unit test class for OspfAreaImpl.
 */
public class OspfAreaImplTest {

    private OspfAreaImpl ospfArea;
    private int result;
    private OspfInterfaceImpl ospfInterface;
    private HashMap<String, OspfNbr> ospfNbrList;
    private List<OspfInterface> ospfInterfaces;
    private OspfInterfaceImpl ospfInterface1;
    private OspfInterfaceImpl ospfInterface2;
    private OspfInterfaceImpl ospfInterface3;
    private OspfInterfaceImpl ospfInterface4;
    private OspfInterfaceImpl ospfInterface5;
    private OspfInterfaceImpl ospfInterface6;
    private NetworkLsa networkLsa;
    private OspfNbrImpl ospfNbr;
    private RouterLsa routerLsa;
    private List<OspfAreaAddressRange> ospfAreaAddressRanges;
    private LsaHeader lsaHeader;
    private TopologyForDeviceAndLink topologyForDeviceAndLink;

    @Before
    public void setUp() throws Exception {
        ospfArea = new OspfAreaImpl();
        topologyForDeviceAndLink = new TopologyForDeviceAndLinkImpl();
    }

    @After
    public void tearDown() throws Exception {
        ospfArea = null;
        ospfInterface = null;
        ospfNbrList = null;
        ospfInterfaces = null;
        ospfAreaAddressRanges = null;
        lsaHeader = null;
        routerLsa = null;
        ospfNbr = null;
        networkLsa = null;
        ospfInterface1 = null;
        ospfInterface2 = null;
        ospfInterface3 = null;
        ospfInterface4 = null;
        ospfInterface5 = null;
        ospfInterface6 = null;

    }

    /**
     * Tests equals() method.
     */
    @Test
    public void testEquals() throws Exception {
        ospfArea = new OspfAreaImpl();
        ospfInterface = new OspfInterfaceImpl();
        ospfArea.setTransitCapability(true);
        ospfArea.setExternalRoutingCapability(true);
        ospfArea.setStubCost(100);
        ospfArea.initializeDb();
        ospfArea.setAddressRanges(ospfAreaAddressRanges);
        assertThat(ospfArea.equals(ospfArea), is(true));
        ospfArea = EasyMock.createMock(OspfAreaImpl.class);
        assertThat(ospfArea.equals(ospfArea), is(true));
        OspfArea ospfArea = new OspfAreaImpl();
        assertThat(ospfArea.equals(ospfArea), is(true));
    }

    /**
     * Tests hashCode() method.
     */
    @Test
    public void testHashCode() throws Exception {
        result = ospfArea.hashCode();
        assertThat(result, is(notNullValue()));
    }

    /**
     * Tests routerId() getter method.
     */
    @Test
    public void testGetRouterId() throws Exception {
        ospfArea.setRouterId(Ip4Address.valueOf("1.1.1.1"));
        assertThat(ospfArea.routerId(), is(Ip4Address.valueOf("1.1.1.1")));
    }

    /**
     * Tests routerId() setter method.
     */
    @Test
    public void testSetRouterId() throws Exception {
        ospfArea.setRouterId(Ip4Address.valueOf("1.1.1.1"));
        assertThat(ospfArea.routerId(), is(Ip4Address.valueOf("1.1.1.1")));
    }

    /**
     * Tests isOpaqueEnabled() getter method.
     */
    @Test
    public void testSetisOpaqueEnabled() throws Exception {
        ospfArea.setIsOpaqueEnabled(true);
        assertThat(ospfArea.isOpaqueEnabled(), is(true));
    }

    /**
     * Tests isOpaqueEnabled() setter method.
     */
    @Test
    public void testIsOpaqueEnabled() throws Exception {
        ospfArea.setIsOpaqueEnabled(true);
        assertThat(ospfArea.isOpaqueEnabled(), is(true));
    }

    /**
     * Tests initializeDb() method.
     */
    @Test
    public void testInitializeDb() throws Exception {
        ospfArea.initializeDb();
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests refreshArea() method.
     */
    @Test
    public void testRefreshArea() throws Exception {

        ospfInterface = new OspfInterfaceImpl();
        ospfInterface.setState(OspfInterfaceState.DR);
        ospfNbrList = new HashMap();
        ospfNbrList.put("1.1.1.1", new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                                   Ip4Address.valueOf("1.1.1.1"),
                                                   Ip4Address.valueOf("2.2.2.2"), 2,
                                                   new OspfInterfaceChannelHandler(new Controller(),
                                                                                   new OspfAreaImpl(),
                                                                                   new OspfInterfaceImpl()),
                                                   topologyForDeviceAndLink));
        ospfNbrList.put("2.2.2.2", new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                                   Ip4Address.valueOf("1.1.1.1"),
                                                   Ip4Address.valueOf("2.2.2.2"), 2,
                                                   new OspfInterfaceChannelHandler(new Controller(),
                                                                                   new OspfAreaImpl(),
                                                                                   new OspfInterfaceImpl()),
                                                   topologyForDeviceAndLink));
        ospfNbrList.put("3.3.3.3", new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                                   Ip4Address.valueOf("1.1.1.1"),
                                                   Ip4Address.valueOf("2.2.2.2"), 2,
                                                   new OspfInterfaceChannelHandler(new Controller(),
                                                                                   new OspfAreaImpl(),
                                                                                   new OspfInterfaceImpl()),
                                                   topologyForDeviceAndLink));
        ospfNbrList.put("4.4.4.4", new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                                   Ip4Address.valueOf("1.1.1.1"),
                                                   Ip4Address.valueOf("2.2.2.2"), 2,
                                                   new OspfInterfaceChannelHandler(new Controller(),
                                                                                   new OspfAreaImpl(),
                                                                                   new OspfInterfaceImpl()),
                                                   topologyForDeviceAndLink));

        ospfInterface.setListOfNeighbors(ospfNbrList);
        ospfInterface.setIpAddress(Ip4Address.valueOf("10.10.10.10"));
        ospfInterface.setIpNetworkMask(Ip4Address.valueOf("255.255.255.255"));
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterfaces.add(ospfInterface1);
        ospfInterface2 = new OspfInterfaceImpl();
        ospfInterface2.setIpAddress(Ip4Address.valueOf("2.2.2.2"));
        ospfInterfaces.add(ospfInterface2);
        ospfInterface3 = new OspfInterfaceImpl();
        ospfInterface3.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface3);
        ospfArea.setInterfacesLst(ospfInterfaces);
        ospfArea.setRouterId(Ip4Address.valueOf("111.111.111.111"));
        networkLsa = ospfArea.buildNetworkLsa(Ip4Address.valueOf("1.1.1.1"),
                                              Ip4Address.valueOf("255.255.255.255"));
        ospfArea.refreshArea(ospfInterface);
        assertThat(ospfNbrList.size(), is(4));
        assertThat(networkLsa, is(notNullValue()));
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests buildNetworkLsa() method.
     */
    @Test
    public void testBuildNetworkLsa() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterfaces.add(ospfInterface1);
        ospfInterface2 = new OspfInterfaceImpl();
        ospfInterface2.setIpAddress(Ip4Address.valueOf("2.2.2.2"));
        ospfInterfaces.add(ospfInterface2);
        ospfInterface3 = new OspfInterfaceImpl();
        ospfInterface3.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface3);
        ospfArea.setInterfacesLst(ospfInterfaces);
        ospfArea.setRouterId(Ip4Address.valueOf("111.111.111.111"));
        networkLsa = ospfArea.buildNetworkLsa(Ip4Address.valueOf("1.1.1.1"),
                                              Ip4Address.valueOf("255.255.255.255"));
        assertThat(ospfInterfaces.size(), is(3));
        assertThat(networkLsa, is(notNullValue()));
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests buildNetworkLsa() method.
     */
    @Test
    public void testBuildNetworkLsa1() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterface1.setIpNetworkMask(Ip4Address.valueOf("255.255.255.255"));
        ospfInterface1.setState(OspfInterfaceState.POINT2POINT);
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.FULL);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfArea.setInterfacesLst(ospfInterfaces);
        ospfArea.setRouterId(Ip4Address.valueOf("111.111.111.111"));
        networkLsa = ospfArea.buildNetworkLsa(Ip4Address.valueOf("1.1.1.1"),
                                              Ip4Address.valueOf("255.255.255.255"));
        assertThat(ospfInterfaces.size(), is(1));
        assertThat(networkLsa, is(notNullValue()));
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests buildRouterLsa() method.
     */
    @Test
    public void testBuildRouterLsa() throws Exception {
        ospfNbrList = new HashMap();
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.FULL);
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterface1.setState(OspfInterfaceState.DOWN);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfInterface2 = new OspfInterfaceImpl();
        ospfInterface2.setState(OspfInterfaceState.LOOPBACK);
        ospfInterface2.setIpAddress(Ip4Address.valueOf("2.2.2.2"));
        ospfInterface2.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface2);
        ospfInterface3 = new OspfInterfaceImpl();
        ospfInterface3.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterface3.setState(OspfInterfaceState.POINT2POINT);
        ospfInterface3.setIpNetworkMask(Ip4Address.valueOf("255.255.255.255"));
        ospfInterface3.addNeighbouringRouter(ospfNbr);
        ospfInterface3.setListOfNeighbors(ospfNbrList);
        ospfInterfaces.add(ospfInterface3);
        ospfInterface4 = new OspfInterfaceImpl();
        ospfInterface4.setState(OspfInterfaceState.WAITING);
        ospfInterface4.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterface4.setIpNetworkMask(Ip4Address.valueOf("255.255.255.255"));
        ospfInterfaces.add(ospfInterface4);
        ospfInterface5 = new OspfInterfaceImpl();
        ospfInterface5.setState(OspfInterfaceState.DR);
        ospfInterface5.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface5);
        ospfInterface6 = new OspfInterfaceImpl();
        ospfInterface6.setState(OspfInterfaceState.BDR);
        ospfInterface6.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterface6.setDr(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface6);
        ospfArea.setInterfacesLst(ospfInterfaces);
        ospfArea.setRouterId(Ip4Address.valueOf("111.111.111.111"));
        assertThat(ospfInterfaces.size(), is(6));
        routerLsa = ospfArea.buildRouterLsa(ospfInterface1);
        assertThat(routerLsa, is(notNullValue()));
        routerLsa = ospfArea.buildRouterLsa(ospfInterface2);
        assertThat(routerLsa, is(notNullValue()));
        routerLsa = ospfArea.buildRouterLsa(ospfInterface3);
        assertThat(routerLsa, is(notNullValue()));
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests buildRouterLsa() method.
     */
    @Test
    public void testBuildRouterLsa1() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterface1.setIpNetworkMask(Ip4Address.valueOf("255.255.255.255"));
        ospfInterface1.setState(OspfInterfaceState.POINT2POINT);
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.FULL);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfArea.setInterfacesLst(ospfInterfaces);
        ospfArea.setRouterId(Ip4Address.valueOf("111.111.111.111"));
        routerLsa = ospfArea.buildRouterLsa(ospfInterface1);
        assertThat(routerLsa, is(notNullValue()));
    }

    /**
     * Tests areaId() getter method.
     */
    @Test
    public void testGetAreaId() throws Exception {
        ospfArea.setAreaId(Ip4Address.valueOf("1.1.1.1"));
        assertThat(ospfArea.areaId(), is(Ip4Address.valueOf("1.1.1.1")));
    }

    /**
     * Tests areaId() setter method.
     */
    @Test
    public void testSetAreaId() throws Exception {
        ospfArea.setAreaId(Ip4Address.valueOf("1.1.1.1"));
        assertThat(ospfArea.areaId(), is(Ip4Address.valueOf("1.1.1.1")));
    }

    /**
     * Tests addressRanges() getter method.
     */
    @Test
    public void testGetAddressRanges() throws Exception {
        ospfAreaAddressRanges = new ArrayList();
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfArea.setAddressRanges(ospfAreaAddressRanges);
        assertThat(ospfArea.addressRanges().size(), is(4));
    }

    /**
     * Tests addressRanges() setter method.
     */
    @Test
    public void testSetAddressRanges() throws Exception {
        ospfAreaAddressRanges = new ArrayList();
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfAreaAddressRanges.add(new OspfAreaAddressRangeImpl());
        ospfArea.setAddressRanges(ospfAreaAddressRanges);
        assertThat(ospfArea.addressRanges().size(), is(4));
    }

    /**
     * Tests isTransitCapability() getter method.
     */
    @Test
    public void testIsTransitCapability() throws Exception {
        ospfArea.setTransitCapability(true);
        assertThat(ospfArea.isTransitCapability(), is(true));
    }

    /**
     * Tests isTransitCapability() setter method.
     */
    @Test
    public void testSetTransitCapability() throws Exception {
        ospfArea.setTransitCapability(true);
        assertThat(ospfArea.isTransitCapability(), is(true));
    }

    /**
     * Tests isExternalRoutingCapability() getter method.
     */
    @Test
    public void testIsExternalRoutingCapability() throws Exception {
        ospfArea.setExternalRoutingCapability(true);
        assertThat(ospfArea.isExternalRoutingCapability(), is(true));
    }

    /**
     * Tests isExternalRoutingCapability() setter method.
     */
    @Test
    public void testSetExternalRoutingCapability() throws Exception {
        ospfArea.setExternalRoutingCapability(true);
        assertThat(ospfArea.isExternalRoutingCapability(), is(true));
    }

    /**
     * Tests stubCost() getter method.
     */
    @Test
    public void testGetStubCost() throws Exception {
        ospfArea.setStubCost(100);
        assertThat(ospfArea.stubCost(), is(100));
    }

    /**
     * Tests stubCost() setter method.
     */
    @Test
    public void testSetStubCost() throws Exception {
        ospfArea.setStubCost(100);
        assertThat(ospfArea.stubCost(), is(100));
    }

    /**
     * Tests getInterfacesLst() getter method.
     */
    @Test
    public void testGetInterfacesLst() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterfaces.add(ospfInterface1);
        ospfInterface2 = new OspfInterfaceImpl();
        ospfInterface2.setIpAddress(Ip4Address.valueOf("2.2.2.2"));
        ospfInterfaces.add(ospfInterface2);
        ospfInterface3 = new OspfInterfaceImpl();
        ospfInterface3.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface3);
        ospfArea.setInterfacesLst(ospfInterfaces);
        assertThat(ospfInterfaces.size(), is(3));
        assertThat(ospfArea.getInterfacesLst(), is(notNullValue()));
    }

    /**
     * Tests setInterfacesLst() setter method.
     */
    @Test
    public void testSetInterfacesLst() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfInterfaces.add(ospfInterface1);
        ospfInterface2 = new OspfInterfaceImpl();
        ospfInterface2.setIpAddress(Ip4Address.valueOf("2.2.2.2"));
        ospfInterfaces.add(ospfInterface2);
        ospfInterface3 = new OspfInterfaceImpl();
        ospfInterface3.setIpAddress(Ip4Address.valueOf("3.3.3.3"));
        ospfInterfaces.add(ospfInterface3);
        ospfArea.setInterfacesLst(ospfInterfaces);
        assertThat(ospfInterfaces.size(), is(3));
        assertThat(ospfArea.getInterfacesLst(), is(notNullValue()));
    }

    /**
     * Tests noNeighborInLsaExchangeProcess() method.
     */
    @Test
    public void testNoNeighborInLsaExchangeProcess() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.EXCHANGE.EXCHANGE);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfArea.setInterfacesLst(ospfInterfaces);
        assertThat(ospfArea.noNeighborInLsaExchangeProcess(), is(false));
    }

    /**
     * Tests getLsaHeaders() method.
     */
    @Test
    public void testGetLsaHeaders() throws Exception {
        assertThat(ospfArea.getLsaHeaders(true, true).size(), is(0));
    }

    /**
     * Tests getLsa() method.
     */
    @Test
    public void testGetLsa() throws Exception {
        assertThat(ospfArea.getLsa(1, "1.1.1.1", "1.1.1.1"), is(nullValue()));
        assertThat(ospfArea.getLsa(10, "1.1.1.1", "1.1.1.1"), is(nullValue()));
    }

    /**
     * Tests lsaLookup() method.
     */
    @Test
    public void testLsaLookup() throws Exception {
        assertThat(ospfArea.lsaLookup(new RouterLsa()), is(nullValue()));
    }

    /**
     * Tests isNewerOrSameLsa() method.
     */
    @Test
    public void testIsNewerOrSameLsa() throws Exception {
        assertThat(ospfArea.isNewerOrSameLsa(new RouterLsa(), new RouterLsa()), is("same"));
    }

    /**
     * Tests addLsa() method.
     */
    @Test
    public void testAddLsa() throws Exception {
        ospfArea.addLsa(new RouterLsa(), new OspfInterfaceImpl());
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests addLsa() method.
     */
    @Test
    public void testAddLsa1() throws Exception {
        ospfArea.addLsa(new RouterLsa(), false, new OspfInterfaceImpl());
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests addLsaToMaxAgeBin() method.
     */
    @Test
    public void testAddLsaToMaxAgeBin() throws Exception {
        ospfArea.addLsaToMaxAgeBin("111", new LsaWrapperImpl());
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests setDbRouterSequenceNumber() method.
     */
    @Test
    public void testSetDbRouterSequenceNumber() throws Exception {
        ospfArea.setDbRouterSequenceNumber(123456);
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests deleteLsa() method.
     */
    @Test
    public void testDeleteLsa() throws Exception {
        ospfArea.deleteLsa(new LsaHeader());
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests removeLsaFromBin() method.
     */
    @Test
    public void testRemoveLsaFromBin() throws Exception {
        ospfArea.removeLsaFromBin(new LsaWrapperImpl());
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests to string method.
     */
    @Test
    public void testToString() throws Exception {
        assertThat(ospfArea.toString(), is(notNullValue()));
    }

    /**
     * Tests getNeighborsInFullState() method.
     */
    @Test
    public void testGetNeighborsinFullState() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.FULL);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfArea.setInterfacesLst(ospfInterfaces);
        assertThat(ospfArea.getNeighborsInFullState(ospfInterface1).size(), is(1));
    }

    /**
     * Tests getLsaKey() method.
     */
    @Test
    public void testGetLsaKey() throws Exception {
        lsaHeader = new LsaHeader();
        lsaHeader.setAdvertisingRouter(Ip4Address.valueOf("1.1.1.1"));
        assertThat(ospfArea.getLsaKey(lsaHeader), is(notNullValue()));
    }

    /**
     * Tests addToOtherNeighborLsaTxList() method.
     */
    @Test
    public void testAddToOtherNeighborLsaTxList() throws Exception {
        ospfInterfaces = new ArrayList();
        ospfInterface1 = new OspfInterfaceImpl();
        ospfInterface1.setIpAddress(Ip4Address.valueOf("1.1.1.1"));
        ospfNbr = new OspfNbrImpl(new OspfAreaImpl(), new OspfInterfaceImpl(),
                                  Ip4Address.valueOf("1.1.1.1"),
                                  Ip4Address.valueOf("2.2.2.2"), 2,
                                  new OspfInterfaceChannelHandler(new Controller(),
                                                                  new OspfAreaImpl(),
                                                                  new OspfInterfaceImpl()),
                                  topologyForDeviceAndLink);
        ospfNbr.setState(OspfNeighborState.FULL);
        ospfInterface1.addNeighbouringRouter(ospfNbr);
        ospfInterfaces.add(ospfInterface1);
        ospfArea.setInterfacesLst(ospfInterfaces);
        lsaHeader = new LsaHeader();
        lsaHeader.setAdvertisingRouter(Ip4Address.valueOf("1.1.1.1"));
        ospfArea.addToOtherNeighborLsaTxList(lsaHeader);
        assertThat(ospfArea, is(notNullValue()));
    }

    /**
     * Tests options() getter method.
     */
    @Test
    public void testGetOptions() throws Exception {
        ospfArea.setOptions(2);
        assertThat(ospfArea.options(), is(2));
    }

    /**
     * Tests options() setter method.
     */
    @Test
    public void testSetOptions() throws Exception {
        ospfArea.setOptions(2);
        assertThat(ospfArea.options(), is(2));
    }

    /**
     * Tests isOpaqueEnabled() method.
     */
    @Test
    public void testGetOpaqueEnabledOptions() throws Exception {
        ospfArea.setIsOpaqueEnabled(true);
        assertThat(ospfArea.isOpaqueEnabled(), is(true));
    }

    /**
     * Tests database()  method.
     */
    @Test
    public void testGetDatabase() throws Exception {
        assertThat(ospfArea.database(), is(notNullValue()));
    }

    /**
     * Tests opaqueEnabledOptions()  method.
     */
    @Test
    public void testOpaqueEnabledOptionsa() throws Exception {
        assertThat(ospfArea.opaqueEnabledOptions(), is(66));
    }
}