// 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.network.lb;

import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.UnsupportedServiceException;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.lb.LoadBalancingRulesService;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.UserVO;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import junit.framework.TestCase;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.cloudstack.test.utils.SpringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;

import javax.inject.Inject;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * This class is responsible for unittesting the methods defined in ApplicationLoadBalancerService
 *
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class ApplicationLoadBalancerTest extends TestCase {
    //The interface to test
    @Inject
    ApplicationLoadBalancerManagerImpl _appLbSvc;

    //The interfaces below are mocked
    @Inject
    ApplicationLoadBalancerRuleDao _lbDao;
    @Inject
    LoadBalancingRulesManager _lbMgr;
    @Inject
    NetworkModel _ntwkModel;
    @Inject
    AccountManager _accountMgr;
    @Inject
    FirewallRulesDao _firewallDao;
    @Inject
    UsageEventDao _usageEventDao;
    @Inject
    LoadBalancingRulesService _lbService;

    public static long existingLbId = 1L;
    public static long nonExistingLbId = 2L;

    public static long validGuestNetworkId = 1L;
    public static long invalidGuestNetworkId = 2L;
    public static long validPublicNetworkId = 3L;

    public static long validAccountId = 1L;
    public static long invalidAccountId = 2L;

    public String validRequestedIp = "10.1.1.1";

    @Override
    @Before
    public void setUp() {
        ComponentContext.initComponentsLifeCycle();
        //mockito for .getApplicationLoadBalancer tests
        Mockito.when(_lbDao.findById(1L)).thenReturn(new ApplicationLoadBalancerRuleVO());
        Mockito.when(_lbDao.findById(2L)).thenReturn(null);

        //mockito for .deleteApplicationLoadBalancer tests
        Mockito.when(_lbService.deleteLoadBalancerRule(existingLbId, true)).thenReturn(true);
        Mockito.when(_lbService.deleteLoadBalancerRule(nonExistingLbId, true)).thenReturn(false);

        //mockito for .createApplicationLoadBalancer tests
        NetworkVO guestNetwork = new NetworkVO(TrafficType.Guest, null, null, 1, null, 1, 1L, false);
        setId(guestNetwork, validGuestNetworkId);
        guestNetwork.setCidr("10.1.1.1/24");

        NetworkVO publicNetwork = new NetworkVO(TrafficType.Public, null, null, 1, null, 1, 1L, false);

        Mockito.when(_ntwkModel.getNetwork(validGuestNetworkId)).thenReturn(guestNetwork);
        Mockito.when(_ntwkModel.getNetwork(invalidGuestNetworkId)).thenReturn(null);
        Mockito.when(_ntwkModel.getNetwork(validPublicNetworkId)).thenReturn(publicNetwork);

        Mockito.when(_accountMgr.getAccount(validAccountId)).thenReturn(new AccountVO());
        Mockito.when(_accountMgr.getAccount(invalidAccountId)).thenReturn(null);
        Mockito.when(_ntwkModel.areServicesSupportedInNetwork(validGuestNetworkId, Service.Lb)).thenReturn(true);
        Mockito.when(_ntwkModel.areServicesSupportedInNetwork(invalidGuestNetworkId, Service.Lb)).thenReturn(false);

        ApplicationLoadBalancerRuleVO lbRule =
            new ApplicationLoadBalancerRuleVO("new", "new", 22, 22, "roundrobin", validGuestNetworkId, validAccountId, 1L, new Ip(validRequestedIp), validGuestNetworkId,
                Scheme.Internal);
        Mockito.when(_lbDao.persist(ArgumentMatchers.any(ApplicationLoadBalancerRuleVO.class))).thenReturn(lbRule);

        Mockito.when(_lbMgr.validateLbRule(ArgumentMatchers.any(LoadBalancingRule.class))).thenReturn(true);

        Mockito.when(_firewallDao.setStateToAdd(ArgumentMatchers.any(FirewallRuleVO.class))).thenReturn(true);

        Mockito.when(_accountMgr.getSystemUser()).thenReturn(new UserVO(1));
        Mockito.when(_accountMgr.getSystemAccount()).thenReturn(new AccountVO(2));
        CallContext.register(_accountMgr.getSystemUser(), _accountMgr.getSystemAccount());

        Mockito.when(_ntwkModel.areServicesSupportedInNetwork(ArgumentMatchers.anyLong(), ArgumentMatchers.any(Network.Service.class))).thenReturn(true);

        Map<Network.Capability, String> caps = new HashMap<Network.Capability, String>();
        caps.put(Capability.SupportedProtocols, NetUtils.TCP_PROTO);
        Mockito.when(_ntwkModel.getNetworkServiceCapabilities(ArgumentMatchers.anyLong(), ArgumentMatchers.any(Network.Service.class))).thenReturn(caps);

        Mockito.when(_lbDao.countBySourceIp(new Ip(validRequestedIp), validGuestNetworkId)).thenReturn(1L);

    }

    @Override
    @After
    public void tearDown() {
        CallContext.unregister();
    }

    /**
     * TESTS FOR .getApplicationLoadBalancer
     */

    @Test
    //Positive test - retrieve existing lb
        public
        void searchForExistingLoadBalancer() {
        ApplicationLoadBalancerRule rule = _appLbSvc.getApplicationLoadBalancer(existingLbId);
        assertNotNull("Couldn't find existing application load balancer", rule);
    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - try to retrieve non-existing lb
        public
        void searchForNonExistingLoadBalancer() throws InvalidParameterValueException {
        _appLbSvc.getApplicationLoadBalancer(nonExistingLbId);
    }

    /**
     * TESTS FOR .deleteApplicationLoadBalancer
     */

    @Test
    //Positive test - delete existing lb
        public
        void deleteExistingLoadBalancer() {
        boolean result = false;
        try {
            result = _appLbSvc.deleteApplicationLoadBalancer(existingLbId);
        } finally {
            assertTrue("Couldn't delete existing application load balancer", result);
        }
    }

    @Test
    //Negative test - try to delete non-existing lb
        public
        void deleteNonExistingLoadBalancer() {
        boolean result = true;
        try {
            result = _appLbSvc.deleteApplicationLoadBalancer(nonExistingLbId);
        } finally {
            assertFalse("Didn't fail when try to delete non-existing load balancer", result);
        }
    }

    /**
     * TESTS FOR .createApplicationLoadBalancer
     * @throws NetworkRuleConflictException
     * @throws InsufficientVirtualNetworkCapacityException
     * @throws InsufficientAddressCapacityException
     */

    @Test(expected = CloudRuntimeException.class)
    //Positive test
        public
        void createValidLoadBalancer() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validGuestNetworkId, validRequestedIp, 22, 22, "roundrobin", validGuestNetworkId,
            validAccountId, true);
    }

    @Test(expected = UnsupportedServiceException.class)
    //Negative test - only internal scheme value is supported in the current release
        public
        void createPublicLoadBalancer() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Public, validGuestNetworkId, validRequestedIp, 22, 22, "roundrobin", validGuestNetworkId,
            validAccountId, true);
    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - invalid SourcePort
        public
        void createWithInvalidSourcePort() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validGuestNetworkId, validRequestedIp, 65536, 22, "roundrobin", validGuestNetworkId,
            validAccountId, true);
    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - invalid instancePort
        public
        void createWithInvalidInstandePort() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validGuestNetworkId, validRequestedIp, 22, 65536, "roundrobin", validGuestNetworkId,
            validAccountId, true);

    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - invalid algorithm
        public
        void createWithInvalidAlgorithm() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        String expectedExcText = null;
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validGuestNetworkId, validRequestedIp, 22, 22, "invalidalgorithm",
            validGuestNetworkId, validAccountId, true);

    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - invalid sourceNetworkId (of Public type, which is not supported)
        public
        void createWithInvalidSourceIpNtwk() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {
        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validPublicNetworkId, validRequestedIp, 22, 22, "roundrobin", validGuestNetworkId,
            validAccountId, true);

    }

    @Test(expected = InvalidParameterValueException.class)
    //Negative test - invalid requested IP (outside of guest network cidr range)
        public
        void createWithInvalidRequestedIp() throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException, NetworkRuleConflictException {

        _appLbSvc.createApplicationLoadBalancer("alena", "alena", Scheme.Internal, validGuestNetworkId, "10.2.1.1", 22, 22, "roundrobin", validGuestNetworkId,
            validAccountId, true);
    }

    private static NetworkVO setId(NetworkVO vo, long id) {
        NetworkVO voToReturn = vo;
        Class<?> c = voToReturn.getClass();
        try {
            Field f = c.getDeclaredField("id");
            f.setAccessible(true);
            f.setLong(voToReturn, id);
        } catch (NoSuchFieldException ex) {
            return null;
        } catch (IllegalAccessException ex) {
            return null;
        }

        return voToReturn;
    }

    @Configuration
    @ComponentScan(basePackageClasses = {NetUtils.class, ApplicationLoadBalancerManagerImpl.class},
                   includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)},
                   useDefaultFilters = false)
    public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {

        @Bean
        public ApplicationLoadBalancerRuleDao applicationLoadBalancerDao() {
            return Mockito.mock(ApplicationLoadBalancerRuleDao.class);
        }

        @Bean
        IpAddressManager ipAddressManager() {
            return Mockito.mock(IpAddressManager.class);
        }

        @Bean
        public NetworkModel networkModel() {
            return Mockito.mock(NetworkModel.class);
        }

        @Bean
        public AccountManager accountManager() {
            return Mockito.mock(AccountManager.class);
        }

        @Bean
        public LoadBalancingRulesManager loadBalancingRulesManager() {
            return Mockito.mock(LoadBalancingRulesManager.class);
        }

        @Bean
        public LoadBalancingRulesService loadBalancingRulesService() {
            return Mockito.mock(LoadBalancingRulesService.class);
        }

        @Bean
        public FirewallRulesDao firewallRulesDao() {
            return Mockito.mock(FirewallRulesDao.class);
        }

        @Bean
        public ResourceTagDao resourceTagDao() {
            return Mockito.mock(ResourceTagDao.class);
        }

        @Bean
        public NetworkOrchestrationService networkManager() {
            return Mockito.mock(NetworkOrchestrationService.class);
        }

        @Bean
        public UsageEventDao UsageEventDao() {
            return Mockito.mock(UsageEventDao.class);
        }

        public static class Library implements TypeFilter {
            @Override
            public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
                mdr.getClassMetadata().getClassName();
                ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
                return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
            }
        }
    }

}
