// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.apache.cloudstack.internallbelement;

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

import javax.inject.Inject;

import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VirtualRouterProvider.VirtualRouterProviderType;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.element.VirtualRouterProviderVO;
import com.cloud.user.AccountManager;
import com.cloud.utils.component.ComponentContext;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/lb_element.xml")
public class InternalLbElementServiceTest {
    //The interface to test
    @Inject InternalLoadBalancerElementService _lbElSvc;
    
    //Mocked interfaces
    @Inject AccountManager _accountMgr;
    @Inject VirtualRouterProviderDao _vrProviderDao;
    @Inject PhysicalNetworkServiceProviderDao _pNtwkProviderDao;
    
    long validElId = 1L;
    long nonExistingElId = 2L;
    long invalidElId = 3L; //not of VirtualRouterProviderType
    
    long validProviderId = 1L;
    long nonExistingProviderId = 2L;
    long invalidProviderId = 3L;
        

    @Before
    public void setUp() {
        
        ComponentContext.initComponentsLifeCycle();
        VirtualRouterProviderVO validElement = new VirtualRouterProviderVO(1, VirtualRouterProviderType.InternalLbVm);
        VirtualRouterProviderVO invalidElement = new VirtualRouterProviderVO(1, VirtualRouterProviderType.VirtualRouter);
        
        Mockito.when(_vrProviderDao.findById(validElId)).thenReturn(validElement);
        Mockito.when(_vrProviderDao.findById(invalidElId)).thenReturn(invalidElement);
        
        Mockito.when(_vrProviderDao.persist(validElement)).thenReturn(validElement);
        
        Mockito.when(_vrProviderDao.findByNspIdAndType(validProviderId, VirtualRouterProviderType.InternalLbVm)).thenReturn(validElement);
        
        PhysicalNetworkServiceProviderVO validProvider = new PhysicalNetworkServiceProviderVO(1, "InternalLoadBalancerElement");
        PhysicalNetworkServiceProviderVO invalidProvider = new PhysicalNetworkServiceProviderVO(1, "Invalid name!");

        Mockito.when(_pNtwkProviderDao.findById(validProviderId)).thenReturn(validProvider);
        Mockito.when(_pNtwkProviderDao.findById(invalidProviderId)).thenReturn(invalidProvider);
        
        Mockito.when(_vrProviderDao.persist(Mockito.any(VirtualRouterProviderVO.class))).thenReturn(validElement); 
    }
    
    //TESTS FOR getInternalLoadBalancerElement METHOD
    
    
    @Test (expected = InvalidParameterValueException.class)
    public void findNonExistingVm() {
        String expectedExcText = null;
        try {
            _lbElSvc.getInternalLoadBalancerElement(nonExistingElId); 
        } catch (InvalidParameterValueException e) {
            expectedExcText = e.getMessage();
            throw e;
        } finally {
            assertEquals("Test failed. The non-existing intenral lb provider was found"
        + expectedExcText, expectedExcText, "Unable to find InternalLoadBalancerElementService by id");
        }
    }
    
    
    @Test (expected = InvalidParameterValueException.class)
    public void findInvalidVm() {
        String expectedExcText = null;
        try {
            _lbElSvc.getInternalLoadBalancerElement(invalidElId); 
        } catch (InvalidParameterValueException e) {
            expectedExcText = e.getMessage();
            throw e;
        } finally {
            assertEquals("Test failed. The non-existing intenral lb provider was found"
                    + expectedExcText, expectedExcText, "Unable to find InternalLoadBalancerElementService by id");
        }
    }
    
    
    @Test
    public void findValidVm() {
        VirtualRouterProvider provider = null;
        try {
            provider = _lbElSvc.getInternalLoadBalancerElement(validElId); 
        } finally {
            assertNotNull("Test failed. Couldn't find the VR provider by the valid id",provider); 
        }
    }
    
    
    //TESTS FOR configureInternalLoadBalancerElement METHOD
    
    @Test (expected = InvalidParameterValueException.class)
    public void configureNonExistingVm() {
        
        _lbElSvc.configureInternalLoadBalancerElement(nonExistingElId, true); 
        
    }
    
    
    @Test (expected = InvalidParameterValueException.class)
    public void ConfigureInvalidVm() {
        _lbElSvc.configureInternalLoadBalancerElement(invalidElId, true);    
    }
    
    
    @Test
    public void enableProvider() {
        VirtualRouterProvider provider = null;
        try {
            provider = _lbElSvc.configureInternalLoadBalancerElement(validElId, true); 
        } finally {
            assertNotNull("Test failed. Couldn't find the VR provider by the valid id ",provider);
            assertTrue("Test failed. The provider wasn't eanbled ", provider.isEnabled()); 
        }
    }
    
    @Test
    public void disableProvider() {
        VirtualRouterProvider provider = null;
        try {
            provider = _lbElSvc.configureInternalLoadBalancerElement(validElId, false); 
        } finally {
            assertNotNull("Test failed. Couldn't find the VR provider by the valid id ",provider);
            assertFalse("Test failed. The provider wasn't disabled ", provider.isEnabled()); 
        }
    } 
    
    //TESTS FOR addInternalLoadBalancerElement METHOD
    
    @Test (expected = InvalidParameterValueException.class)
    public void addToNonExistingProvider() {
        
        _lbElSvc.addInternalLoadBalancerElement(nonExistingProviderId); 
        
    }
    
    public void addToInvalidProvider() {
        _lbElSvc.addInternalLoadBalancerElement(invalidProviderId);   
    }
    
    @Test
    public void addToExistingProvider() {
        _lbElSvc.addInternalLoadBalancerElement(validProviderId);
    }

}


