/**
*    Copyright 2012 Big Switch Networks, Inc. 
* 
*    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 net.floodlightcontroller.devicemanager.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Iterator;

import org.junit.Test;
import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField;
import junit.framework.TestCase;

/**
 * 
 * @author gregor
 *
 */
public class DeviceUniqueIndexTest extends TestCase {
    protected Entity e1a;
    protected Entity e1b;
    protected Device d1;
    protected Entity e2;
    protected Entity e2alt;
    protected Entity e3;
    protected Entity e4;
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        e1a = new Entity(1L, (short)1, 1, 1L, 1, new Date());
        e1b = new Entity(1L, (short)2, 1, 1L, 1, new Date());
        List<Entity> d1Entities = new ArrayList<Entity>(2);
        d1Entities.add(e1a);
        d1Entities.add(e1b);
        d1 = new Device(null, Long.valueOf(1), null, null, d1Entities, null);
        
        // e2 and e2 alt match in MAC and VLAN
        e2 = new Entity(2L, (short)2, 2, 2L, 2, new Date());
        e2alt = new Entity(2, (short)2, null, null, null, null);
        
        // IP is null
        e3 = new Entity(3L, (short)3, null, 3L, 3, new Date());
        
        // IP and switch and port are null
        e4 = new Entity(4L, (short)4, null, null, null, new Date());
    }
    
    /*
     * Checks that the iterator it returns the elements in the Set expected
     * Doesn't check how often an element is returned as long it's at least
     * once
     */
    protected void verifyIterator(Set<Long> expected, Iterator<Long> it) {
        HashSet<Long> actual = new HashSet<Long>();
        while (it.hasNext()) {
            actual.add(it.next());
        }
        assertEquals(expected, actual);
    }
    
    @Test
    public void testDeviceUniqueIndex() {
        DeviceUniqueIndex idx1 = new DeviceUniqueIndex(
                                             EnumSet.of(DeviceField.MAC, 
                                                        DeviceField.VLAN));
        
        idx1.updateIndex(d1, d1.getDeviceKey());
        idx1.updateIndex(e2, 2L);
        
        //-------------
        // Test findByEntity lookups
        assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a));
        assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
        assertEquals(Long.valueOf(2L), idx1.findByEntity(e2));
        // we didn't add e2alt but since they key fields are the same we 
        // should find it 
        assertEquals(Long.valueOf(2L), idx1.findByEntity(e2alt));
        assertEquals(null, idx1.findByEntity(e3));
        assertEquals(null, idx1.findByEntity(e4));
        
        //-------------
        // Test getAll()
        HashSet<Long> expectedKeys = new HashSet<Long>();
        expectedKeys.add(1L);
        expectedKeys.add(2L);
        verifyIterator(expectedKeys, idx1.getAll());
        
                
        //-------------
        // Test queryByEntity()
        verifyIterator(Collections.<Long>singleton(1L), 
                       idx1.queryByEntity(e1a));
        verifyIterator(Collections.<Long>singleton(1L), 
                       idx1.queryByEntity(e1b));
        verifyIterator(Collections.<Long>singleton(2L), 
                       idx1.queryByEntity(e2));
        verifyIterator(Collections.<Long>singleton(2L),
                       idx1.queryByEntity(e2alt));
        assertEquals(false, idx1.queryByEntity(e3).hasNext());
        assertEquals(false, idx1.queryByEntity(e3).hasNext());
        
        
        //-------------
        // Test removal
        idx1.removeEntity(e1a, 42L); // No-op. e1a isn't mapped to this key
        assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a));
        idx1.removeEntity(e1a, 1L); 
        assertEquals(null, idx1.findByEntity(e1a));
        assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
        assertEquals(Long.valueOf(2L), idx1.findByEntity(e2));
        idx1.removeEntity(e2);  
        assertEquals(null, idx1.findByEntity(e2));
        assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
        
        
        //-------------
        // Test null keys
        DeviceUniqueIndex idx2 = new DeviceUniqueIndex(
                                             EnumSet.of(DeviceField.IPV4,
                                                        DeviceField.SWITCH));
        // only one key field is null
        idx2.updateIndex(e3, 3L);
        assertEquals(Long.valueOf(3L), idx2.findByEntity(e3));
        e3.ipv4Address = 3;
        assertEquals(null, idx2.findByEntity(e3));
        // all key fields are null
        idx2.updateIndex(e4, 4L);
        assertEquals(null, idx2.findByEntity(e4));
        Device d4 = new Device(null, 4L, null, null, Collections.<Entity>singleton(e4), null);
        idx2.updateIndex(d4, 4L);
        assertEquals(null, idx2.findByEntity(e4));
        
        

        //-------------
        // entity already exists with different deviceKey
        DeviceUniqueIndex idx3 = new DeviceUniqueIndex(
                                             EnumSet.of(DeviceField.MAC, 
                                                        DeviceField.VLAN));
        idx3.updateIndex(e1a, 42L);
        assertEquals(false, idx3.updateIndex(d1, 1L));
        // TODO: shouldn't this fail as well so that the behavior
        // is consistent?
        idx3.updateIndex(e1a, 1L);
        // anyways. We can now add d1 ;-)
        assertEquals(true, idx3.updateIndex(d1, 1L));
    }
}
