org.midonet.midolman.host.updater.DefaultInterfaceDataUpdaterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.midonet.midolman.host.updater.DefaultInterfaceDataUpdaterTest.java

Source

/*
 * Copyright 2014 Midokura SARL
 *
 * 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.midonet.midolman.host.updater;

import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import scala.collection.JavaConversions;

import akka.actor.Actor;
import akka.testkit.TestActorRef;
import akka.testkit.TestKit;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.codahale.metrics.Clock;

import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.zookeeper.CreateMode;
import org.hamcrest.beans.HasPropertyWithValue;
import org.junit.Before;
import org.junit.Test;

import org.midonet.cluster.config.ZookeeperConfig;
import org.midonet.midolman.guice.InterfaceScannerModule;
import org.midonet.midolman.guice.MidolmanModule;
import org.midonet.midolman.guice.ResourceProtectionModule;
import org.midonet.midolman.guice.cluster.ClusterClientModule;
import org.midonet.midolman.guice.config.ConfigProviderModule;
import org.midonet.midolman.guice.datapath.MockDatapathModule;
import org.midonet.midolman.guice.serialization.SerializationModule;
import org.midonet.midolman.guice.state.MockFlowStateStorageModule;
import org.midonet.midolman.guice.zookeeper.MockZookeeperConnectionModule;
import org.midonet.midolman.host.guice.HostModule;
import org.midonet.midolman.host.interfaces.InterfaceDescription;
import org.midonet.midolman.host.state.HostDirectory;
import org.midonet.midolman.host.state.HostZkManager;
import org.midonet.midolman.serialization.SerializationException;
import org.midonet.midolman.state.Directory;
import org.midonet.midolman.state.MockDirectory;
import org.midonet.midolman.state.StateAccessException;
import org.midonet.midolman.state.ZkPathManager;
import org.midonet.midolman.util.guice.MockMidolmanModule;
import org.midonet.midolman.util.guice.TestableMidolmanActorsModule;
import org.midonet.midolman.version.DataWriteVersion;
import org.midonet.midolman.version.guice.VersionModule;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsMapContaining.hasEntry;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.midonet.midolman.host.state.HostDirectory.Interface;

public class DefaultInterfaceDataUpdaterTest {

    InterfaceDataUpdater updater;
    HostZkManager hostManager;
    Directory directory;
    ZkPathManager pathManager;

    UUID hostID;
    HostDirectory.Metadata metadata;

    @Before
    public void setUp() throws Exception {

        final Directory cleanDirectory = new MockDirectory();
        pathManager = new ZkPathManager("");
        cleanDirectory.add("/hosts", null, CreateMode.PERSISTENT);
        cleanDirectory.add(pathManager.getWriteVersionPath(), DataWriteVersion.CURRENT.getBytes(),
                CreateMode.PERSISTENT);

        final HierarchicalConfiguration configuration = new HierarchicalConfiguration();
        configuration.addNodes(ZookeeperConfig.GROUP_NAME,
                Arrays.asList(new HierarchicalConfiguration.Node("midolman_root_key", "")));

        Injector injector = Guice.createInjector(new VersionModule(), new SerializationModule(),
                new ConfigProviderModule(configuration), new MockFlowStateStorageModule(), new MockDatapathModule(),
                new MockZookeeperConnectionModule(), new HostModule(), new ClusterClientModule(),
                new MockMidolmanModule(),
                new TestableMidolmanActorsModule(JavaConversions.mapAsScalaMap(new HashMap<String, TestKit>()),
                        JavaConversions.mapAsScalaMap(new HashMap<String, TestActorRef<Actor>>()),
                        Clock.defaultClock()),
                new ResourceProtectionModule(), new InterfaceScannerModule());

        directory = injector.getInstance(Directory.class);
        directory.add("/hosts", null, CreateMode.PERSISTENT);
        directory.add(pathManager.getWriteVersionPath(), DataWriteVersion.CURRENT.getBytes(),
                CreateMode.PERSISTENT);

        updater = injector.getInstance(InterfaceDataUpdater.class);
        hostManager = injector.getInstance(HostZkManager.class);

        hostID = UUID.randomUUID();
        metadata = new HostDirectory.Metadata();

        metadata.setName("test");
        metadata.setAddresses(new InetAddress[] {});

        hostManager.createHost(hostID, new HostDirectory.Metadata());
    }

    @Test
    public void testNoInterfaces() throws Exception {
        Map<String, Interface> interfaceMap;

        interfaceMap = assertStoreDescriptions();
        assertThat("The number of interfaces is zero", interfaceMap.entrySet(), hasSize(0));
    }

    @Test
    public void testOneInterface() throws Exception {
        InterfaceDescription description = new InterfaceDescription("testInterface");
        assertStoreDescriptions(description);
    }

    @Test
    public void testUpdateInterfaceData() throws Exception {
        Map<String, Interface> interfaceMap;
        String testInterfaceName = "testInterface";

        InterfaceDescription description = new InterfaceDescription(testInterfaceName);
        description.setMac("11:11:11:11:11:11");

        interfaceMap = assertStoreDescriptions(description);

        HostDirectory.Interface hostInterface = interfaceMap.get(description.getName());

        assertThat("The interface object has the same name as a the one saved", hostInterface.getMac(),
                equalTo(description.getMac()));

        // update some data and validate that the returned values are properly
        // updated
        description.setMac("11:11:11:11:11:12");

        interfaceMap = assertStoreDescriptions(description);
        assertThat("The interface object has the same name as a the one saved",
                interfaceMap.get(description.getName()).getMac(), equalTo(description.getMac()));
    }

    @Test
    public void testRenameInterface() throws Exception {
        Map<String, HostDirectory.Interface> hostInterfaces;

        InterfaceDescription description = new InterfaceDescription("test-before");
        description.setMac("11:11:11:11:11:11");

        hostInterfaces = assertStoreDescriptions(description);

        assertThat("Exactly one interface should appear inside the datastore " + "directory.",
                hostInterfaces.entrySet(), hasSize(1));

        Interface hostInterface = hostInterfaces.get(description.getName());
        assertThat("The new interface object should have the proper mac", hostInterface.getMac(),
                equalTo(description.getMac()));

        // change the name
        description.setName("test-after");
        hostInterfaces = assertStoreDescriptions(description);
        Interface newHostInterface = hostInterfaces.get(description.getName());

        assertThat("The interface should have the same mac", newHostInterface.getMac(),
                equalTo(description.getMac()));
    }

    @Test
    public void testTwoInterfaces() throws Exception {
        InterfaceDescription first = new InterfaceDescription("first");
        first.setMac("11:11:11:11:11:11");

        InterfaceDescription second = new InterfaceDescription("second");
        second.setMac("11:11:11:11:11:12");

        assertStoreDescriptions(first, second);

        // validate removal of an interface and adding of a new one
        second.setName("second-updated");
        assertStoreDescriptions(first, second);

        // validate removal of all interfaces
        assertStoreDescriptions();
    }

    @Test
    public void testNonUpdatedInterface() throws Exception {
        String name = "first";

        InterfaceDescription first = new InterfaceDescription(name);
        first.setMac("11:11:11:11:11:11");

        Map<String, Interface> boundInterfaces = assertStoreDescriptions(first);

        HostDirectory.Interface hostInterface = boundInterfaces.get(name);

        for (int i = 0; i < 10; i++) {
            Map<String, Interface> newBoundInterfaces = assertStoreDescriptions(first);

            assertThat(newBoundInterfaces.entrySet(), hasSize(boundInterfaces.size()));
            assertThat(newBoundInterfaces, hasEntry(equalTo(name),
                    HasPropertyWithValue.<Interface>hasProperty("name", equalTo(hostInterface.getName()))));
        }

        assertStoreDescriptions(first);
    }

    /**
     * This method will take an array of descriptions, add them to the datastore
     * using the updater and after that will read the data directly from the
     * datastore, validate that all the entries have UUIDs and that the new
     * objects map properly to interface names.
     *
     * @param descriptions the descriptions that we want to store
     * @return a mapping from interface name to interface object.
     *
     * @throws StateAccessException when the datastore operations fail.
     */
    private Map<String, Interface> assertStoreDescriptions(InterfaceDescription... descriptions)
            throws StateAccessException, SerializationException {

        updater.updateInterfacesData(hostID, metadata, new HashSet<>(Arrays.asList(descriptions)));

        Set<String> interfaces = hostManager.getInterfaces(hostID);

        assertThat("The datastore interfaces count should be correct one.", interfaces,
                hasSize(descriptions.length));

        Set<String> interfaceNames = new HashSet<String>();

        for (InterfaceDescription description : descriptions) {
            interfaceNames.add(description.getName());
        }

        Map<String, Interface> nameToHostInterfaceMap = new HashMap<String, Interface>();

        for (String interfaceName : interfaces) {
            Interface hostInterface = hostManager.getInterfaceData(hostID, interfaceName);

            assertThat("The interface object is not a null value", hostInterface, notNullValue());

            assertThat("The interface object should have an known name", interfaceNames,
                    hasItem(hostInterface.getName()));

            interfaceNames.remove(hostInterface.getName());

            nameToHostInterfaceMap.put(hostInterface.getName(), hostInterface);
        }

        assertThat("No interfaces with unknown names should have been stored", interfaceNames, hasSize(0));

        return nameToHostInterfaceMap;
    }
}