// 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
// 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 com.cloud.resourcelimit;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.TaggedResourceLimitAndCountResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.reservation.dao.ReservationDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;

import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.configuration.Resource;
import com.cloud.configuration.ResourceCountVO;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.projects.ProjectVO;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.EntityManager;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vpc.MockResourceLimitManagerImpl;

@RunWith(MockitoJUnitRunner.class)
public class ResourceLimitManagerImplTest {
    private Logger logger = LogManager.getLogger(ResourceLimitManagerImplTest.class);

    MockResourceLimitManagerImpl _resourceLimitService = new MockResourceLimitManagerImpl();

    @Spy
    @InjectMocks
    ResourceLimitManagerImpl resourceLimitManager;

    @Mock
    VMInstanceDao vmDao;
    @Mock
    AccountDao accountDao;
    @Mock
    AccountManager accountManager;
    @Mock
    ResourceLimitDao resourceLimitDao;
    @Mock
    DomainDao domainDao;
    @Mock
    ProjectDao projectDao;
    @Mock
    ResourceCountDao resourceCountDao;
    @Mock
    private ReservationDao reservationDao;
    @Mock
    UserVmJoinDao userVmJoinDao;
    @Mock
    ServiceOfferingDao serviceOfferingDao;
    @Mock
    VMTemplateDao vmTemplateDao;
    @Mock
    DiskOfferingDao diskOfferingDao;
    @Mock
    VolumeDao volumeDao;
    @Mock
    UserVmDao userVmDao;
    @Mock
    EntityManager entityManager;
    @Mock
    SnapshotDataStoreDao snapshotDataStoreDao;

    private CallContext callContext;
    private List<String> hostTags = List.of("htag1", "htag2", "htag3");
    private List<String> storageTags = List.of("stag1", "stag2");

    private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
        Field f = ConfigKey.class.getDeclaredField(name);
        f.setAccessible(true);
        f.set(configKey, o);
    }


    @Before
    public void setUp() throws Exception {
        overrideDefaultConfigValue(ResourceLimitService.ResourceLimitHostTags, "_defaultValue", StringUtils.join(hostTags, ","));
        overrideDefaultConfigValue(ResourceLimitService.ResourceLimitStorageTags, "_defaultValue", StringUtils.join(storageTags, ","));

        Account account = mock(Account.class);
        User user = mock(User.class);
        CallContext.register(user, account);
    }

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

    @Test
    public void testInjected() throws Exception {
        logger.info("Starting test for Resource Limit manager");
        updateResourceCount();
        updateResourceLimit();
        //listResourceLimits();
        logger.info("Resource Limit Manager: TEST PASSED");
    }

    protected void updateResourceCount() {
        // update resource count for an account
        Long accountId = (long)1;
        Long domainId = (long)1;
        String msg = "Update Resource Count for account: TEST FAILED";
        Assert.assertNull(msg, _resourceLimitService.recalculateResourceCount(accountId, domainId, null));

        // update resource count for a domain
        accountId = null;
        msg = "Update Resource Count for domain: TEST FAILED";
        Assert.assertNull(msg, _resourceLimitService.recalculateResourceCount(accountId, domainId, null));
    }

    protected void updateResourceLimit() {
        // update resource Limit for an account for resource_type = 8 (CPU)
        resourceLimitServiceCall((long)1, (long)1, 8, (long)20);

        // update resource Limit for a domain for resource_type = 8 (CPU)
        resourceLimitServiceCall(null, (long)1, 8, (long)40);

        // update resource Limit for an account for resource_type = 9 (Memory (in MiB))
        resourceLimitServiceCall((long)1, (long)1, 9, (long)4096);

        // update resource Limit for a domain for resource_type = 9 (Memory (in MiB))
        resourceLimitServiceCall(null, (long)1, 9, (long)10240);

        // update resource Limit for an account for resource_type = 10 (Primary storage (in GiB))
        resourceLimitServiceCall((long)1, (long)1, 10, (long)200);

        // update resource Limit for a domain for resource_type = 10 (Primary storage (in GiB))
        resourceLimitServiceCall(null, (long)1, 10, (long)200);

        // update resource Limit for an account for resource_type = 11 (Secondary storage (in GiB))
        resourceLimitServiceCall((long)1, (long)1, 10, (long)400);

        // update resource Limit for a domain for resource_type = 11 (Secondary storage (in GiB))
        resourceLimitServiceCall(null, (long)1, 10, (long)400);

        // update resource Limit for an account for resource_type = 5 (Project)
        resourceLimitServiceCall((long) 1, (long) 1, 5, (long) 50);

        // update resource Limit for a domain for resource_type = 5 (Project)
        resourceLimitServiceCall(null, (long) 1, 5, (long) 100);
    }

    private void resourceLimitServiceCall(Long accountId, Long domainId, Integer resourceType, Long max) {
        String msg = "Update Resource Limit: TEST FAILED";
        ResourceLimit result = null;
        try {
            result = _resourceLimitService.updateResourceLimit(accountId, domainId, resourceType, max, null);
            Assert.assertFalse(msg, (result != null || (result == null && max != null && max.longValue() == -1L)));
        } catch (Exception ex) {
            Assert.fail(msg);
        }
    }

    @Test
    public void testRemoveUndesiredTaggedLimits() {
        String desiredTag = "tag1";
        String undesiredTag = "tag2";
        List<ResourceLimitVO> limits = new ArrayList<>();
        limits.add(new ResourceLimitVO(Resource.ResourceType.cpu, 100L, 1L, Resource.ResourceOwnerType.Account, desiredTag));
        limits.add(new ResourceLimitVO(Resource.ResourceType.cpu, 100L, 1L, Resource.ResourceOwnerType.Account, undesiredTag));
        resourceLimitManager.removeUndesiredTaggedLimits(limits, List.of(desiredTag), null);
        Assert.assertEquals(1, limits.size());
        Assert.assertEquals(desiredTag, limits.get(0).getTag());
    }

    @Test
    public void testGetResourceLimitHostTags() {
        List<String> tags = resourceLimitManager.getResourceLimitHostTags();
        Assert.assertEquals(3, tags.size());
        for (int i = 0; i < tags.size(); ++i) {
            Assert.assertEquals(hostTags.get(i), tags.get(i));
        }
    }

    @Test
    public void testGetResourceLimitHostTags1() {
        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
        VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
        Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
        Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(1));
        List<String> tags = resourceLimitManager.getResourceLimitHostTags(serviceOffering, template);
        Assert.assertEquals(2, tags.size());
        Assert.assertEquals(hostTags.get(0), tags.get(0));
        Assert.assertEquals(hostTags.get(1), tags.get(1));
    }

    @Test
    public void testGetResourceLimitStorageTags() {
        List<String> tags = resourceLimitManager.getResourceLimitStorageTags();
        Assert.assertEquals(2, tags.size());
        for (int i = 0; i < tags.size(); ++i) {
            Assert.assertEquals(storageTags.get(i), tags.get(i));
        }
    }

    @Test
    public void testGetResourceLimitStorageTags1() {
        DiskOffering diskOffering = Mockito.mock(DiskOffering.class);
        Mockito.when(diskOffering.getTags()).thenReturn(storageTags.get(1));
        Mockito.when(diskOffering.getTagsArray()).thenReturn(new String[]{storageTags.get(1)});
        List<String> tags = resourceLimitManager.getResourceLimitStorageTags(diskOffering);
        Assert.assertEquals(1, tags.size());
        Assert.assertEquals(storageTags.get(1), tags.get(0));
    }

    @Test
    public void testCheckVmResourceLimit() {
        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
        VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
        Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
        Mockito.when(serviceOffering.getCpu()).thenReturn(2);
        Mockito.when(serviceOffering.getRamSize()).thenReturn(256);
        Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
        Account account = Mockito.mock(Account.class);
        try {
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any());
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
            resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template);
            List<String> tags = new ArrayList<>();
            tags.add(null);
            tags.add(hostTags.get(0));
            for (String tag: tags) {
                Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.user_vm, tag);
                Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, tag, 2L);
                Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, tag, 256L);
            }
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testCheckVmCpuResourceLimit() {
        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
        VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
        Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
        Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
        Account account = Mockito.mock(Account.class);
        long cpu = 2L;
        try {
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
            resourceLimitManager.checkVmCpuResourceLimit(account, true, serviceOffering, template, cpu);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, null, cpu);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), cpu);
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testCheckVmMemoryResourceLimit() {
        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
        VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
        Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
        Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
        Account account = Mockito.mock(Account.class);
        long delta = 256L;
        try {
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
            resourceLimitManager.checkVmMemoryResourceLimit(account, true, serviceOffering, template, delta);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, null, delta);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, hostTags.get(0), delta);
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testCheckVmGpuResourceLimit() {
        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
        VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
        Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
        Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
        Account account = Mockito.mock(Account.class);
        long gpuCount = 2L;
        try {
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
            resourceLimitManager.checkVmGpuResourceLimit(account, true, serviceOffering, template, gpuCount);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.gpu, null, gpuCount);
            Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.gpu, hostTags.get(0), gpuCount);
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testCheckVolumeResourceLimit() {
        String checkTag = storageTags.get(0);
        DiskOffering diskOffering = Mockito.mock(DiskOffering.class);
        Mockito.when(diskOffering.getTags()).thenReturn(checkTag);
        Mockito.when(diskOffering.getTagsArray()).thenReturn(new String[]{checkTag});
        Account account = Mockito.mock(Account.class);
        try {
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any());
            Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
            resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering);
            List<String> tags = new ArrayList<>();
            tags.add(null);
            tags.add(checkTag);
            for (String tag: tags) {
                Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.volume, tag);
                Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 100L);
            }
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testGetResourceLimitTagsForLimitSearch() {
        Pair<List<String>, List<String>> result = resourceLimitManager.getResourceLimitTagsForLimitSearch(null);
        Assert.assertEquals(hostTags, result.first());
        Assert.assertEquals(storageTags, result.second());
        String nonExistentTag = "sometag";
        result = resourceLimitManager.getResourceLimitTagsForLimitSearch(nonExistentTag);
        Assert.assertTrue(CollectionUtils.isEmpty(result.first()));
        Assert.assertTrue(CollectionUtils.isEmpty(result.second()));
        String hostTag = "htag2";
        result = resourceLimitManager.getResourceLimitTagsForLimitSearch(hostTag);
        Assert.assertTrue(CollectionUtils.isNotEmpty(result.first()));
        Assert.assertEquals(1, result.first().size());
        Assert.assertEquals(hostTag, result.first().get(0));
        Assert.assertTrue(CollectionUtils.isEmpty(result.second()));
        String storageTag = "stag1";
        result = resourceLimitManager.getResourceLimitTagsForLimitSearch(storageTag);
        Assert.assertTrue(CollectionUtils.isNotEmpty(result.second()));
        Assert.assertEquals(1, result.second().size());
        Assert.assertEquals(storageTag, result.second().get(0));
        Assert.assertTrue(CollectionUtils.isEmpty(result.first()));
    }

    @Test
    public void testIsTaggedResourceCountRecalculationNotNeeded() {
        Assert.assertTrue(resourceLimitManager.isTaggedResourceCountRecalculationNotNeeded(
                Resource.ResourceType.network, List.of("h1", "h2"), List.of("s1", "s2")));
        Assert.assertTrue(resourceLimitManager.isTaggedResourceCountRecalculationNotNeeded(
                Resource.ResourceType.cpu, new ArrayList<>(), new ArrayList<>()));
        Assert.assertFalse(resourceLimitManager.isTaggedResourceCountRecalculationNotNeeded(
                Resource.ResourceType.cpu, List.of("h1", "h2"), new ArrayList<>()));
    }

    @Test
    public void testAddTaggedResourceLimits() {
        List<ResourceLimitVO> limits = new ArrayList<>();
        resourceLimitManager.addTaggedResourceLimits(limits, null, hostTags, Resource.ResourceOwnerType.Account, 1L);
        Assert.assertTrue(CollectionUtils.isEmpty(limits));
        resourceLimitManager.addTaggedResourceLimits(limits, List.of(Resource.ResourceType.cpu), null, Resource.ResourceOwnerType.Account, 1L);
        Assert.assertTrue(CollectionUtils.isEmpty(limits));
        limits = new ArrayList<>();
        limits.add(Mockito.mock(ResourceLimitVO.class));
        int size = limits.size();
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getId()).thenReturn(1L);
        Mockito.when(accountDao.findById(1L)).thenReturn(account);
        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(true);
        resourceLimitManager.addTaggedResourceLimits(limits, List.of(Resource.ResourceType.cpu), hostTags, Resource.ResourceOwnerType.Account, 1L);
        Assert.assertEquals(size + hostTags.size(), limits.size());
    }

    @Test
    public void testFindCorrectResourceLimitForAccount() {
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getId()).thenReturn(1L);
        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(true);
        long result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(Resource.RESOURCE_UNLIMITED, result);

        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
        ResourceLimitVO limit = new ResourceLimitVO();
        limit.setMax(10L);
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(1L, Resource.ResourceOwnerType.Account, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(limit);
        result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(10L, result);

        long defaultAccountCpuMax = 25L;
        Map<String, Long> accountResourceLimitMap = new HashMap<>();
        accountResourceLimitMap.put(Resource.ResourceType.cpu.name(), defaultAccountCpuMax);
        resourceLimitManager.accountResourceLimitMap = accountResourceLimitMap;
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(1L, Resource.ResourceOwnerType.Account, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(null);
        result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(defaultAccountCpuMax, result);

        result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(defaultAccountCpuMax, result);
    }

    @Test
    public void testFindCorrectResourceLimitForAccountProjects() {
            AccountVO account = Mockito.mock(AccountVO.class);
            Mockito.when(account.getId()).thenReturn(1L);
            Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(true);

            long result = resourceLimitManager.findCorrectResourceLimitForAccount(account,
                            Resource.ResourceType.project, hostTags.get(0));
            Assert.assertEquals(Resource.RESOURCE_UNLIMITED, result);

            Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
            ResourceLimitVO limit = new ResourceLimitVO();
            limit.setMax(10L);
            Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(1L, Resource.ResourceOwnerType.Account,
                            Resource.ResourceType.project, hostTags.get(0))).thenReturn(limit);
            result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.project,
                            hostTags.get(0));
            Assert.assertEquals(10L, result);

            long defaultAccountProjectsMax = 15L;
            Map<String, Long> accountResourceLimitMap = new HashMap<>();
            accountResourceLimitMap.put(Resource.ResourceType.project.name(), defaultAccountProjectsMax);
            resourceLimitManager.accountResourceLimitMap = accountResourceLimitMap;
            Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(1L, Resource.ResourceOwnerType.Account,
                            Resource.ResourceType.project, hostTags.get(0))).thenReturn(null);
            result = resourceLimitManager.findCorrectResourceLimitForAccount(account, Resource.ResourceType.project,
                            hostTags.get(0));
            Assert.assertEquals(defaultAccountProjectsMax, result);
    }

    @Test
    public void testFindCorrectResourceLimitForAccountId1() {
        long accountId = 1L;
        Mockito.when(accountManager.isRootAdmin(accountId)).thenReturn(true);
        long result = resourceLimitManager.findCorrectResourceLimitForAccount(accountId, null, Resource.ResourceType.cpu);
        Assert.assertEquals(Resource.RESOURCE_UNLIMITED, result);

        accountId = 2L;
        AccountVO account = mock(AccountVO.class);
        Mockito.when(accountManager.isRootAdmin(accountId)).thenReturn(false);
        Mockito.when(accountDao.findById(accountId)).thenReturn(account);
        Long limit = 100L;
        result = resourceLimitManager.findCorrectResourceLimitForAccount(accountId, limit, Resource.ResourceType.cpu);
        Assert.assertEquals(limit.longValue(), result);

        long defaultAccountCpuMax = 25L;
        Mockito.when(accountManager.isRootAdmin(accountId)).thenReturn(false);
        Map<String, Long> accountResourceLimitMap = new HashMap<>();
        accountResourceLimitMap.put(Resource.ResourceType.cpu.name(), defaultAccountCpuMax);
        resourceLimitManager.accountResourceLimitMap = accountResourceLimitMap;
        result = resourceLimitManager.findCorrectResourceLimitForAccount(accountId, null, Resource.ResourceType.cpu);
        Assert.assertEquals(defaultAccountCpuMax, result);
    }

    @Test
    public void testFindCorrectResourceLimitForDomain() {
        DomainVO domain = Mockito.mock(DomainVO.class);
        Mockito.when(domain.getId()).thenReturn(1L);
        long result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(Resource.RESOURCE_UNLIMITED, result);

        Mockito.when(domain.getId()).thenReturn(2L);
        Mockito.when(domain.getParent()).thenReturn(null);
        ResourceLimitVO limit = new ResourceLimitVO();
        limit.setMax(100L);
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(2L, Resource.ResourceOwnerType.Domain, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(limit);
        result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(100L, result);

        Mockito.when(domain.getId()).thenReturn(3L);
        DomainVO parentDomain = Mockito.mock(DomainVO.class);
        Mockito.when(domain.getParent()).thenReturn(5L);
        Mockito.when(domainDao.findById(5L)).thenReturn(parentDomain);
        limit = new ResourceLimitVO();
        limit.setMax(200L);
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(3L, Resource.ResourceOwnerType.Domain, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(null);
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(5L, Resource.ResourceOwnerType.Domain, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(limit);
        result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(200L, result);

        long defaultDomainCpuMax = 250L;
        Mockito.when(domain.getId()).thenReturn(4L);
        Mockito.when(domain.getParent()).thenReturn(null);
        Map<String, Long> domainResourceLimitMap = new HashMap<>();
        domainResourceLimitMap.put(Resource.ResourceType.cpu.name(), defaultDomainCpuMax);
        resourceLimitManager.domainResourceLimitMap = domainResourceLimitMap;
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(4L, Resource.ResourceOwnerType.Domain, Resource.ResourceType.cpu, hostTags.get(0))).thenReturn(null);
        result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.cpu, hostTags.get(0));
        Assert.assertEquals(defaultDomainCpuMax, result);
    }

    @Test
    public void testResourceUnlimitedForDomainProjects() {
            DomainVO domain = Mockito.mock(DomainVO.class);
            Mockito.when(domain.getId()).thenReturn(1L);

            long result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.project,
                            hostTags.get(0));
            Assert.assertEquals(Resource.RESOURCE_UNLIMITED, result);
    }
    @Test
    public void testSpecificLimitForDomainProjects() {
        DomainVO domain = Mockito.mock(DomainVO.class);
        Mockito.when(domain.getId()).thenReturn(2L);

        ResourceLimitVO limit = new ResourceLimitVO();
        limit.setMax(100L);
        Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(2L, Resource.ResourceOwnerType.Domain, Resource.ResourceType.project, hostTags.get(0))).thenReturn(limit);

        long result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.project, hostTags.get(0));
        Assert.assertEquals(100L, result);
    }

    @Test
    public void testParentDomainLimitForDomainProjects() {
            DomainVO domain = Mockito.mock(DomainVO.class);
            Mockito.when(domain.getId()).thenReturn(3L);

            DomainVO parentDomain = Mockito.mock(DomainVO.class);
            Mockito.when(domain.getParent()).thenReturn(5L);
            Mockito.when(domainDao.findById(5L)).thenReturn(parentDomain);

            ResourceLimitVO limit = new ResourceLimitVO();
            limit.setMax(200L);
            Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(3L, Resource.ResourceOwnerType.Domain,
                            Resource.ResourceType.project, hostTags.get(0))).thenReturn(null);
            Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(5L, Resource.ResourceOwnerType.Domain,
                            Resource.ResourceType.project, hostTags.get(0))).thenReturn(limit);

            long result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.project,
                            hostTags.get(0));
            Assert.assertEquals(200L, result);
    }

    @Test
    public void testDefaultDomainProjectLimit() {
            DomainVO domain = Mockito.mock(DomainVO.class);
            Mockito.when(domain.getId()).thenReturn(4L);
            Mockito.when(domain.getParent()).thenReturn(null);

            long defaultDomainProjectsMax = 250L;
            Map<String, Long> domainResourceLimitMap = new HashMap<>();
            domainResourceLimitMap.put(Resource.ResourceType.project.name(), defaultDomainProjectsMax);
            resourceLimitManager.domainResourceLimitMap = domainResourceLimitMap;

            Mockito.when(resourceLimitDao.findByOwnerIdAndTypeAndTag(4L, Resource.ResourceOwnerType.Domain,
                            Resource.ResourceType.project, hostTags.get(0))).thenReturn(null);

            long result = resourceLimitManager.findCorrectResourceLimitForDomain(domain, Resource.ResourceType.project,
                            hostTags.get(0));
            Assert.assertEquals(defaultDomainProjectsMax, result);
    }

    @Test
    public void testCheckResourceLimitWithTag() {
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getId()).thenReturn(1L);
        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(true);
        try {
            resourceLimitManager.checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), 1);
        } catch (ResourceAllocationException e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testCheckResourceLimitWithTagNonAdmin() throws ResourceAllocationException {
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getId()).thenReturn(1L);
        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
        Mockito.doReturn(new ArrayList<ResourceLimitVO>()).when(resourceLimitManager).lockAccountAndOwnerDomainRows(Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Mockito.doNothing().when(resourceLimitManager).checkAccountResourceLimit(account, null, Resource.ResourceType.cpu, hostTags.get(0), 1);
        Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(account, null, Resource.ResourceType.cpu, hostTags.get(0), 1);
        try {
            resourceLimitManager.checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), 1);
        } catch (ResourceAllocationException e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testCheckResourceLimitWithTagProject() throws ResourceAllocationException {
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getId()).thenReturn(1L);
        Mockito.when(account.getType()).thenReturn(Account.Type.PROJECT);
        Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(false);
        ProjectVO projectVO = Mockito.mock(ProjectVO.class);
        Mockito.when(projectDao.findByProjectAccountId(Mockito.anyLong())).thenReturn(projectVO);
        Mockito.doReturn(new ArrayList<ResourceLimitVO>()).when(resourceLimitManager).lockAccountAndOwnerDomainRows(Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Mockito.doNothing().when(resourceLimitManager).checkAccountResourceLimit(account, projectVO, Resource.ResourceType.cpu, hostTags.get(0), 1);
        Mockito.doNothing().when(resourceLimitManager).checkDomainResourceLimit(account, projectVO, Resource.ResourceType.cpu, hostTags.get(0), 1);
        try {
            resourceLimitManager.checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), 1);
        } catch (ResourceAllocationException e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testRemoveResourceLimitAndCountForNonMatchingTags() {
        resourceLimitManager.removeResourceLimitAndCountForNonMatchingTags(1L, Resource.ResourceOwnerType.Account, hostTags, storageTags);
        Mockito.verify(resourceLimitDao, Mockito.times(1))
                .removeResourceLimitsForNonMatchingTags(1L, Resource.ResourceOwnerType.Account, ResourceLimitService.HostTagsSupportingTypes, hostTags);
        Mockito.verify(resourceLimitDao, Mockito.times(1))
                .removeResourceLimitsForNonMatchingTags(1L, Resource.ResourceOwnerType.Account, ResourceLimitService.StorageTagsSupportingTypes, storageTags);
        Mockito.verify(resourceCountDao, Mockito.times(1))
                .removeResourceCountsForNonMatchingTags(1L, Resource.ResourceOwnerType.Account, ResourceLimitService.HostTagsSupportingTypes, hostTags);
        Mockito.verify(resourceCountDao, Mockito.times(1))
                .removeResourceCountsForNonMatchingTags(1L, Resource.ResourceOwnerType.Account, ResourceLimitService.StorageTagsSupportingTypes, storageTags);
    }

    @Test
    public void testRecalculateAccountTaggedResourceCountNegative() {
        List<ResourceCountVO> result = resourceLimitManager.recalculateAccountTaggedResourceCount(1L, Resource.ResourceType.network, hostTags, storageTags);
        CollectionUtils.isEmpty(result);
        result = resourceLimitManager.recalculateAccountTaggedResourceCount(1L, Resource.ResourceType.cpu, null, storageTags);
        CollectionUtils.isEmpty(result);
        result = resourceLimitManager.recalculateAccountTaggedResourceCount(1L, Resource.ResourceType.volume, hostTags, null);
        CollectionUtils.isEmpty(result);
    }

    @Test
    public void testRecalculateAccountTaggedResourceCountHostTypes() {
        long accountId = 1L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        for (String tag: hostTags) {
            Mockito.doReturn(10L).when(resourceLimitManager).recalculateAccountResourceCount(accountId, type, tag);
        }
        List<ResourceCountVO> result = resourceLimitManager.recalculateAccountTaggedResourceCount(accountId, type, hostTags, storageTags);
        Assert.assertEquals(hostTags.size(), result.size());
    }

    @Test
    public void testRecalculateAccountTaggedResourceCountStorageTypes() {
        long accountId = 1L;
        Resource.ResourceType type = Resource.ResourceType.volume;
        for (String tag: storageTags) {
            Mockito.doReturn(10L).when(resourceLimitManager).recalculateAccountResourceCount(accountId, type, tag);
        }
        List<ResourceCountVO> result = resourceLimitManager.recalculateAccountTaggedResourceCount(accountId, type, hostTags, storageTags);
        Assert.assertEquals(storageTags.size(), result.size());
    }

    @Test
    public void testRecalculateDomainTaggedResourceCountNegative() {
        List<ResourceCountVO> result = resourceLimitManager.recalculateDomainTaggedResourceCount(1L, Resource.ResourceType.network, hostTags, storageTags);
        CollectionUtils.isEmpty(result);
        result = resourceLimitManager.recalculateDomainTaggedResourceCount(1L, Resource.ResourceType.cpu, null, storageTags);
        CollectionUtils.isEmpty(result);
        result = resourceLimitManager.recalculateDomainTaggedResourceCount(1L, Resource.ResourceType.volume, hostTags, null);
        CollectionUtils.isEmpty(result);
    }

    @Test
    public void testRecalculateDomainTaggedResourceCountHostTypes() {
        long domainId = 1L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        for (String tag: hostTags) {
            Mockito.doReturn(10L).when(resourceLimitManager).recalculateDomainResourceCount(domainId, type, tag);
        }
        List<ResourceCountVO> result = resourceLimitManager.recalculateDomainTaggedResourceCount(domainId, type, hostTags, storageTags);
        Assert.assertEquals(hostTags.size(), result.size());
    }

    @Test
    public void testRecalculateDomainTaggedResourceCountStorageTypes() {
        long domainId = 1L;
        Resource.ResourceType type = Resource.ResourceType.volume;
        for (String tag: storageTags) {
            Mockito.doReturn(10L).when(resourceLimitManager).recalculateDomainResourceCount(domainId, type, tag);
        }
        List<ResourceCountVO> result = resourceLimitManager.recalculateDomainTaggedResourceCount(domainId, type, hostTags, storageTags);
        Assert.assertEquals(storageTags.size(), result.size());
    }

    @Test
    public void testRecalculateResourceCount() {
        Long accountId = 1L;
        Long domainId = null;
        Integer typeId = Resource.ResourceType.user_vm.getOrdinal();
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager).recalculateResourceCount(accountId, domainId, typeId, null);
        resourceLimitManager.recalculateResourceCount(accountId, domainId, typeId);
        Mockito.verify(resourceLimitManager, Mockito.times(1)).recalculateResourceCount(accountId, domainId, typeId, null);
    }

    @Test
    public void testGetVmsWithAccountAndTagNoTag() throws NoSuchFieldException, IllegalAccessException {
        overrideDefaultConfigValue(VirtualMachineManager.ResourceCountRunningVMsonly, "_defaultValue", "false");
        List<VirtualMachine.State> states = Arrays.asList(VirtualMachine.State.Destroyed, VirtualMachine.State.Error, VirtualMachine.State.Expunging);
        List<UserVmJoinVO> vmList = List.of(Mockito.mock(UserVmJoinVO.class));
        Mockito.when(userVmJoinDao.listByAccountServiceOfferingTemplateAndNotInState(1L, states, null, null)).thenReturn(vmList);
        List<UserVmJoinVO> result = resourceLimitManager.getVmsWithAccountAndTag(1L, null);
        Assert.assertEquals(vmList.size(), result.size());
    }

    @Test
    public void testGetVmsWithAccountAndTagNegative() {
        String tag = hostTags.get(0);
        Mockito.when(serviceOfferingDao.listIdsByHostTag(tag)).thenReturn(null);
        Mockito.when(vmTemplateDao.listIdsByTemplateTag(tag)).thenReturn(null);
        List<UserVmJoinVO> result = resourceLimitManager.getVmsWithAccountAndTag(1L, hostTags.get(0));
        Assert.assertTrue(CollectionUtils.isEmpty(result));
    }

    @Test
    public void testGetVmsWithAccountAndTag() throws NoSuchFieldException, IllegalAccessException {
        overrideDefaultConfigValue(VirtualMachineManager.ResourceCountRunningVMsonly, "_defaultValue", "true");
        String tag = hostTags.get(0);
        Mockito.when(serviceOfferingDao.listIdsByHostTag(tag)).thenReturn(List.of(1L));
        Mockito.when(vmTemplateDao.listIdsByTemplateTag(tag)).thenReturn(List.of(1L));
        List<UserVmJoinVO> vmList = List.of(Mockito.mock(UserVmJoinVO.class));
        Mockito.when(userVmJoinDao.listByAccountServiceOfferingTemplateAndNotInState(Mockito.anyLong(), Mockito.anyList(), Mockito.anyList(), Mockito.anyList())).thenReturn(vmList);
        List<UserVmJoinVO> result = resourceLimitManager.getVmsWithAccountAndTag(1L, tag);
        Assert.assertEquals(vmList.size(), result.size());
    }

    @Test
    public void testGetVmsWithAccount() {
        long accountId = 1L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager).getVmsWithAccountAndTag(accountId, null);
        resourceLimitManager.getVmsWithAccount(accountId);
        Mockito.verify(resourceLimitManager, Mockito.times(1)).getVmsWithAccountAndTag(accountId, null);
    }

    @Test
    public void testGetVolumesWithAccountAndTag() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.when(diskOfferingDao.listByStorageTag(tag)).thenReturn(new ArrayList<>());
        Assert.assertTrue(CollectionUtils.isEmpty(resourceLimitManager.getVolumesWithAccountAndTag(accountId, tag)));

        Mockito.when(diskOfferingDao.listByStorageTag(tag)).thenReturn(List.of(Mockito.mock(DiskOfferingVO.class)));
        Mockito.when(vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId)).thenReturn(List.of(1L));
        Mockito.when(volumeDao.listAllocatedVolumesForAccountDiskOfferingIdsAndNotForVms(
                Mockito.anyLong(), Mockito.anyList(), Mockito.anyList()))
                .thenReturn(List.of(Mockito.mock(VolumeVO.class)));
        List<VolumeVO> result = resourceLimitManager.getVolumesWithAccountAndTag(accountId, tag);
        Assert.assertTrue(CollectionUtils.isNotEmpty(resourceLimitManager.getVolumesWithAccountAndTag(accountId, tag)));
        Assert.assertEquals(1, result.size());
    }

    @Test
    public void testCalculateVmCountForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.when(userVmDao.countAllocatedVMsForAccount(Mockito.eq(accountId), Mockito.anyBoolean()))
                .thenReturn(1L);
        Assert.assertEquals(1L, resourceLimitManager.calculateVmCountForAccount(accountId, tag));

        tag = "";
        Mockito.when(userVmDao.countAllocatedVMsForAccount(Mockito.eq(accountId), Mockito.anyBoolean()))
                .thenReturn(2L);
        Assert.assertEquals(2L, resourceLimitManager.calculateVmCountForAccount(accountId, tag));

        tag = "tag";
        UserVmJoinVO vm = Mockito.mock(UserVmJoinVO.class);
        Mockito.when(vm.getId()).thenReturn(1L);
        Mockito.doReturn(List.of(vm)).when(resourceLimitManager).getVmsWithAccountAndTag(accountId, tag);
        Assert.assertEquals(1L, resourceLimitManager.calculateVmCountForAccount(accountId, tag));
    }

    @Test
    public void testCalculateVolumeCountForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.when(vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId))
                .thenReturn(List.of(1L));
        Mockito.when(volumeDao.countAllocatedVolumesForAccount(accountId)).thenReturn(3L);
        Assert.assertEquals(2L, resourceLimitManager.calculateVolumeCountForAccount(accountId, tag));

        tag = "";
        Mockito.when(volumeDao.countAllocatedVolumesForAccount(accountId)).thenReturn(2L);
        Assert.assertEquals(1L, resourceLimitManager.calculateVolumeCountForAccount(accountId, tag));

        tag = "tag";
        Mockito.doReturn(List.of(VolumeVO.class)).when(resourceLimitManager).getVolumesWithAccountAndTag(accountId, tag);
        Assert.assertEquals(1L, resourceLimitManager.calculateVolumeCountForAccount(accountId, tag));
    }

    @Test
    public void testCalculateVmCpuCountForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.doReturn(1L).when(resourceLimitManager).countCpusForAccount(accountId);
        Assert.assertEquals(1L, resourceLimitManager.calculateVmCpuCountForAccount(accountId, tag));

        tag = "";
        Mockito.doReturn(2L).when(resourceLimitManager).countCpusForAccount(accountId);
        Assert.assertEquals(2L, resourceLimitManager.calculateVmCpuCountForAccount(accountId, tag));

        tag = "tag";
        UserVmJoinVO vm = Mockito.mock(UserVmJoinVO.class);
        int cpu = 2;
        Mockito.when(vm.getCpu()).thenReturn(cpu);
        List<UserVmJoinVO> vms = List.of(vm, vm);
        Mockito.doReturn(vms).when(resourceLimitManager).getVmsWithAccountAndTag(accountId, tag);
        Assert.assertEquals(vms.size() * cpu, resourceLimitManager.calculateVmCpuCountForAccount(accountId, tag));
    }

    @Test
    public void testCalculateVmMemoryCountForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.doReturn(1024L).when(resourceLimitManager).calculateMemoryForAccount(accountId);
        Assert.assertEquals(1024L, resourceLimitManager.calculateVmMemoryCountForAccount(accountId, tag));

        tag = "";
        Mockito.doReturn(2048L).when(resourceLimitManager).calculateMemoryForAccount(accountId);
        Assert.assertEquals(2048L, resourceLimitManager.calculateVmMemoryCountForAccount(accountId, tag));

        tag = "tag";
        UserVmJoinVO vm = Mockito.mock(UserVmJoinVO.class);
        int memory = 1024;
        Mockito.when(vm.getRamSize()).thenReturn(memory);
        List<UserVmJoinVO> vms = List.of(vm, vm);
        Mockito.doReturn(vms).when(resourceLimitManager).getVmsWithAccountAndTag(accountId, tag);
        Assert.assertEquals(vms.size() * memory, resourceLimitManager.calculateVmMemoryCountForAccount(accountId, tag));
    }

    @Test
    public void testCalculateVmGpuCountForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.doReturn(1L).when(resourceLimitManager).calculateGpuForAccount(accountId);
        Assert.assertEquals(1L, resourceLimitManager.calculateVmGpuCountForAccount(accountId, tag));

        tag = "";
        Mockito.doReturn(2L).when(resourceLimitManager).calculateGpuForAccount(accountId);
        Assert.assertEquals(2L, resourceLimitManager.calculateVmGpuCountForAccount(accountId, tag));

        tag = "tag";
        UserVmJoinVO vm = Mockito.mock(UserVmJoinVO.class);
        int gpuCount = 2;
        Mockito.when(vm.getGpuCount()).thenReturn(gpuCount);
        List<UserVmJoinVO> vms = List.of(vm, vm);
        Mockito.doReturn(vms).when(resourceLimitManager).getVmsWithAccountAndTag(accountId, tag);
        Assert.assertEquals(vms.size() * gpuCount, resourceLimitManager.calculateVmGpuCountForAccount(accountId, tag));
    }

    @Test
    public void testCalculatePrimaryStorageForAccount() {
        long accountId = 1L;
        String tag = null;
        Mockito.when(vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId))
                .thenReturn(List.of(1L));
        Mockito.when(snapshotDataStoreDao.getSnapshotsPhysicalSizeOnPrimaryStorageByAccountId(accountId)).thenReturn(100L);
        Mockito.when(volumeDao.primaryStorageUsedForAccount(Mockito.eq(accountId), Mockito.anyList())).thenReturn(100L);
        Assert.assertEquals(200L, resourceLimitManager.calculatePrimaryStorageForAccount(accountId, tag));

        tag = "";
        Mockito.when(volumeDao.primaryStorageUsedForAccount(Mockito.eq(accountId), Mockito.anyList())).thenReturn(200L);
        Assert.assertEquals(300L, resourceLimitManager.calculatePrimaryStorageForAccount(accountId, tag));

        tag = "tag";
        VolumeVO vol = Mockito.mock(VolumeVO.class);
        long size = 1024;
        Mockito.when(vol.getSize()).thenReturn(size);
        List<VolumeVO> vols = List.of(vol, vol);
        Mockito.doReturn(vols).when(resourceLimitManager).getVolumesWithAccountAndTag(accountId, tag);
        Assert.assertEquals((vols.size() * size) + 100L, resourceLimitManager.calculatePrimaryStorageForAccount(accountId, tag));
    }

    @Test
    public void testGetResourceCount() {
        long accountId = 1L;
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getId()).thenReturn(accountId);
        resourceLimitManager.getResourceCount(account, Resource.ResourceType.user_vm, "tag");
        Mockito.verify(resourceCountDao, Mockito.times(1))
                .getResourceCount(accountId, Resource.ResourceOwnerType.Account, Resource.ResourceType.user_vm, "tag");
    }

    @Test
    public void testGetTaggedResourceLimitAndCountResponse() {
        long accountId = 1L;
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getId()).thenReturn(accountId);
        Long accountLimit = 10L;
        Mockito.doReturn(accountLimit).when(resourceLimitManager)
                .findCorrectResourceLimitForAccount(Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Long accountCount = 2L;
        ResourceCountVO resourceCountVO = Mockito.mock(ResourceCountVO.class);
        Mockito.when(resourceCountVO.getCount()).thenReturn(accountCount);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceOwnerType.Account), Mockito.any(Resource.ResourceType.class),
                Mockito.anyString())).thenReturn(resourceCountVO);

        TaggedResourceLimitAndCountResponse res = resourceLimitManager.getTaggedResourceLimitAndCountResponse(account,
                null, Resource.ResourceOwnerType.Account, Resource.ResourceType.user_vm, "tag");
        Assert.assertEquals(accountLimit, res.getLimit());
        Assert.assertEquals(accountCount, res.getTotal());
        Long available = accountLimit - accountCount;
        Assert.assertEquals(available, res.getAvailable());


        long domainId = 1L;
        Domain domain = Mockito.mock(Domain.class);
        Mockito.when(domain.getId()).thenReturn(domainId);
        Long domainLimit = 20L;
        Mockito.doReturn(domainLimit).when(resourceLimitManager)
                .findCorrectResourceLimitForDomain(Mockito.any(Domain.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Long domainCount = 4L;
        Mockito.when(resourceCountVO.getCount()).thenReturn(domainCount);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.any(Resource.ResourceType.class),
                Mockito.anyString())).thenReturn(resourceCountVO);
        res = resourceLimitManager.getTaggedResourceLimitAndCountResponse(null,
                domain, Resource.ResourceOwnerType.Domain, Resource.ResourceType.user_vm, "tag");
        Assert.assertEquals(domainLimit, res.getLimit());
        Assert.assertEquals(domainCount, res.getTotal());
        available = domainLimit - domainCount;
        Assert.assertEquals(available, res.getAvailable());
    }

    @Test
    public void testUpdateTaggedResourceLimitsAndCountsForAccounts() {
        String tag = "tag";
        resourceLimitManager.updateTaggedResourceLimitsAndCountsForAccounts(
                List.of(Mockito.mock(AccountResponse.class)), "tag");
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .updateTaggedResourceLimitsAndCountsForAccountsOrDomains(Mockito.anyList(),
                        Mockito.eq(null), Mockito.eq(tag));
    }

    @Test
    public void updateTaggedResourceLimitsAndCountsForDomains() {
        String tag = "tag";
        resourceLimitManager.updateTaggedResourceLimitsAndCountsForDomains(
                List.of(Mockito.mock(DomainResponse.class)), "tag");
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .updateTaggedResourceLimitsAndCountsForAccountsOrDomains(Mockito.eq(null),
                        Mockito.anyList(), Mockito.eq(tag));
    }

    private void mockCheckResourceLimitWithTag() throws ResourceAllocationException {
        Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
                Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
                Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString(), Mockito.anyLong());
    }

    private void mockIncrementResourceCountWithTag() {
        Mockito.doNothing().when(resourceLimitManager).incrementResourceCountWithTag(
                Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Mockito.doNothing().when(resourceLimitManager).incrementResourceCountWithTag(
                Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString(), Mockito.anyLong());
    }

    private void mockDecrementResourceCountWithTag() {
        Mockito.doNothing().when(resourceLimitManager).decrementResourceCountWithTag(
                Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
        Mockito.doNothing().when(resourceLimitManager).decrementResourceCountWithTag(
                Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString(), Mockito.anyLong());
    }

    @Test
    public void testCheckVolumeResourceCount() throws ResourceAllocationException {
        Account account = Mockito.mock(Account.class);
        String tag = "tag";
        long delta = 10L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        resourceLimitManager.incrementVolumeResourceCount(1L, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).checkResourceLimitWithTag(Mockito.any(Account.class),
                Mockito.eq(Resource.ResourceType.volume), Mockito.anyString());
        Mockito.verify(resourceLimitManager, Mockito.never()).checkResourceLimitWithTag(Mockito.any(Account.class),
                Mockito.eq(Resource.ResourceType.primary_storage), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        mockCheckResourceLimitWithTag();
        resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(
                account, Resource.ResourceType.volume, tag);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 10L);
    }

    @Test
    public void testIncrementVolumeResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        long delta = 10L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        resourceLimitManager.incrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.volume), Mockito.anyString());
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.primary_storage), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        mockIncrementResourceCountWithTag();
        resourceLimitManager.incrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1)).incrementResourceCountWithTag(
                1L, Resource.ResourceType.volume, tag);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.primary_storage, tag, delta);
    }

    @Test
    public void testDecrementVolumeResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        long delta = 10L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        resourceLimitManager.decrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.volume), Mockito.anyString());
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.primary_storage), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        mockDecrementResourceCountWithTag();
        resourceLimitManager.decrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1)).decrementResourceCountWithTag(
                1L, Resource.ResourceType.volume, tag);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.primary_storage, tag, delta);
    }

    @Test
    public void testIncrementVolumePrimaryStorageResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        long delta = 10L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        resourceLimitManager.incrementVolumePrimaryStorageResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.primary_storage), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        mockIncrementResourceCountWithTag();
        resourceLimitManager.incrementVolumePrimaryStorageResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.primary_storage, tag, delta);
    }

    @Test
    public void testDecrementVolumePrimaryStorageResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        long delta = 10L;
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        resourceLimitManager.decrementVolumePrimaryStorageResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.primary_storage), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
        mockDecrementResourceCountWithTag();
        resourceLimitManager.decrementVolumePrimaryStorageResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.primary_storage, tag, delta);
    }

    @Test
    public void testIncrementVmResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.incrementVmResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.user_vm), Mockito.anyString());
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.cpu), Mockito.anyString(), Mockito.anyLong());
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.memory), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockIncrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        int cpu = 1;
        Mockito.when(offering.getCpu()).thenReturn(cpu);
        int memory = 1024;
        Mockito.when(offering.getRamSize()).thenReturn(memory);
        resourceLimitManager.incrementVmResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1)).incrementResourceCountWithTag(
                1L, Resource.ResourceType.user_vm, tag);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.cpu, tag, Long.valueOf(cpu));
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.memory, tag, Long.valueOf(memory));
    }

    @Test
    public void testDecrementVmResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.decrementVmResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class));
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.user_vm), Mockito.anyString());
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.cpu), Mockito.anyString(), Mockito.anyLong());
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.memory), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockDecrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        int cpu = 1;
        Mockito.when(offering.getCpu()).thenReturn(cpu);
        int memory = 1024;
        Mockito.when(offering.getRamSize()).thenReturn(memory);
        resourceLimitManager.decrementVmResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class));
        Mockito.verify(resourceLimitManager, Mockito.times(1)).decrementResourceCountWithTag(
                1L, Resource.ResourceType.user_vm, tag);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.cpu, tag, Long.valueOf(cpu));
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.memory, tag, Long.valueOf(memory));
    }

    @Test
    public void testIncrementVmCpuResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.incrementVmCpuResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.cpu), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockIncrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        Long cpu = 2L;
        resourceLimitManager.incrementVmCpuResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), cpu);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.cpu, tag, cpu);
    }

    @Test
    public void testDecrementVmCpuResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.decrementVmCpuResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.cpu), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockDecrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        int cpu = 1;
        Mockito.when(offering.getCpu()).thenReturn(cpu);
        resourceLimitManager.decrementVmCpuResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.cpu, tag, Long.valueOf(cpu));
    }

    @Test
    public void testIncrementVmMemoryResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.incrementVmMemoryResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.cpu), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockIncrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        long memory = 1024L;
        resourceLimitManager.incrementVmMemoryResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), memory);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.memory, tag, memory);
    }

    @Test
    public void testDecrementVmMemoryResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.decrementVmMemoryResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.memory), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockDecrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        int memory = 1024;
        Mockito.when(offering.getRamSize()).thenReturn(memory);
        resourceLimitManager.decrementVmMemoryResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.memory, tag, Long.valueOf(memory));
    }

    @Test
    public void testIncrementVmGpuResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.incrementVmGpuResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).incrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.gpu), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockIncrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        Long gpuCount = 2L;
        resourceLimitManager.incrementVmGpuResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), gpuCount);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .incrementResourceCountWithTag(accountId, Resource.ResourceType.gpu, tag, gpuCount);
    }


    @Test
    public void testDecrementVmGpuResourceCount() {
        long accountId = 1L;
        String tag = "tag";
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        resourceLimitManager.decrementVmGpuResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.never()).decrementResourceCountWithTag(Mockito.anyLong(),
                Mockito.eq(Resource.ResourceType.gpu), Mockito.anyString(), Mockito.anyLong());

        Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
                .getResourceLimitHostTagsForResourceCountOperation(Mockito.anyBoolean(),
                        Mockito.any(ServiceOffering.class), Mockito.any(VirtualMachineTemplate.class));
        mockDecrementResourceCountWithTag();
        ServiceOffering offering = Mockito.mock(ServiceOffering.class);
        int gpuCount = 1;
        Mockito.when(offering.getGpuCount()).thenReturn(gpuCount);
        resourceLimitManager.decrementVmGpuResourceCount(accountId, false,
                offering, Mockito.mock(VirtualMachineTemplate.class), null);
        Mockito.verify(resourceLimitManager, Mockito.times(1))
                .decrementResourceCountWithTag(accountId, Resource.ResourceType.gpu, tag, Long.valueOf(gpuCount));
    }

    @Test
    public void testUpdateResourceLimitForAccount() {
        Long accountId = 1L;
        Long resourceLimitId = 3L;
        Integer typeId = 13;
        Long maxGB = 10L;
        Long maxBytes = maxGB * Resource.ResourceType.bytesToGiB;

        Account account = mock(Account.class);
        when(entityManager.findById(Account.class, accountId)).thenReturn(account);
        ResourceLimitVO resourceLimitVO = mock(ResourceLimitVO.class);
        when(resourceLimitVO.getId()).thenReturn(resourceLimitId);
        when(resourceLimitDao.findByOwnerIdAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, Resource.ResourceType.backup_storage, null)).thenReturn(resourceLimitVO);

        try (MockedStatic<ActionEventUtils> actionEventUtilsMockedStatic = Mockito.mockStatic(ActionEventUtils.class)) {
            Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
                    Mockito.anyLong(),
                    Mockito.anyString(), Mockito.anyString(),
                    Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);

            resourceLimitManager.updateResourceLimit(accountId, null, typeId, maxGB, null);

            Mockito.verify(resourceLimitDao, Mockito.times(1)).update(resourceLimitId, maxBytes);
            Mockito.verify(resourceLimitDao, Mockito.never()).persist(Mockito.any());
            actionEventUtilsMockedStatic.verify(() -> ActionEventUtils.onActionEvent(0L, 0L, 0L, EventTypes.EVENT_RESOURCE_LIMIT_UPDATE,
                    "Resource limit updated. Resource Type: " + Resource.ResourceType.backup_storage.toString() + ", New Value: " + maxBytes,
                    accountId, ApiCommandResourceType.Account.toString()));
        }
    }

    @Test
    public void testUpdateResourceLimitForDomain() {
        Long domainId = 2L;
        Long resourceLimitId = 3L;
        Integer typeId = 13;
        Long maxGB = 10L;
        Long maxBytes = maxGB * Resource.ResourceType.bytesToGiB;

        Domain domain = mock(Domain.class);
        when(domain.getParent()).thenReturn(null);
        when(entityManager.findById(Domain.class, domainId)).thenReturn(domain);
        ResourceLimitVO resourceLimitVO = mock(ResourceLimitVO.class);
        when(resourceLimitVO.getId()).thenReturn(resourceLimitId);
        when(resourceLimitDao.findByOwnerIdAndTypeAndTag(domainId, Resource.ResourceOwnerType.Domain, Resource.ResourceType.backup_storage, null)).thenReturn(resourceLimitVO);

        try (MockedStatic<ActionEventUtils> actionEventUtilsMockedStatic = Mockito.mockStatic(ActionEventUtils.class)) {
            Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
                    Mockito.anyLong(),
                    Mockito.anyString(), Mockito.anyString(),
                    Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);

            resourceLimitManager.updateResourceLimit(null, domainId, typeId, maxGB, null);

            Mockito.verify(resourceLimitDao, Mockito.times(1)).update(resourceLimitId, maxBytes);
            Mockito.verify(resourceLimitDao, Mockito.never()).persist(Mockito.any());
            actionEventUtilsMockedStatic.verify(() -> ActionEventUtils.onActionEvent(0L, 0L, 0L, EventTypes.EVENT_RESOURCE_LIMIT_UPDATE,
                    "Resource limit updated. Resource Type: " + Resource.ResourceType.backup_storage.toString() + ", New Value: " + maxBytes,
                    domainId, ApiCommandResourceType.Domain.toString()));
        }
    }

    @Test
    public void consolidatedResourceLimitsForAllResourceTypesWithAccountId() {
        Long accountId = 1L;
        Long domainId = null;
        List<ResourceLimitVO> foundLimits = new ArrayList<>();
        ResourceLimitVO limit = new ResourceLimitVO(Resource.ResourceType.cpu, 10L, accountId, Resource.ResourceOwnerType.Account);
        foundLimits.add(limit);

        Mockito.when(accountManager.getAccount(accountId)).thenReturn(Mockito.mock(Account.class));
        Mockito.doReturn(20L).when(resourceLimitManager).findCorrectResourceLimitForAccount(Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());

        List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, true);

        Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
        Assert.assertTrue(result.contains(limit));
    }

    @Test
    public void consolidatedResourceLimitsForAllResourceTypesWithDomainId() {
        Long accountId = null;
        Long domainId = 1L;
        List<ResourceLimitVO> foundLimits = new ArrayList<>();
        ResourceLimitVO limit = new ResourceLimitVO(Resource.ResourceType.memory, 15L, domainId, Resource.ResourceOwnerType.Domain);
        foundLimits.add(limit);

        Mockito.when(domainDao.findById(domainId)).thenReturn(Mockito.mock(DomainVO.class));
        Mockito.doReturn(30L).when(resourceLimitManager).findCorrectResourceLimitForDomain(Mockito.any(Domain.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());

        List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, false);

        Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
        Assert.assertTrue(result.contains(limit));
    }

    @Test
    public void consolidatedResourceLimitsForAllResourceTypesWithEmptyFoundLimits() {
        Long accountId = 1L;
        Long domainId = null;
        List<ResourceLimitVO> foundLimits = new ArrayList<>();

        Mockito.when(accountManager.getAccount(accountId)).thenReturn(Mockito.mock(Account.class));
        Mockito.doReturn(25L).when(resourceLimitManager).findCorrectResourceLimitForAccount(Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.isNull());

        List<ResourceLimitVO> result = resourceLimitManager.getConsolidatedResourceLimitsForAllResourceTypes(accountId, domainId, foundLimits, true);

        Assert.assertEquals(EnumSet.allOf(Resource.ResourceType.class).size(), result.size());
        Assert.assertEquals(25L, result.get(0).getMax().longValue());
    }
}
