// 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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.resourcelimit.Reserver;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;

import org.apache.commons.collections.CollectionUtils;
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.MockedConstruction;
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.ResourceCount;
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.InvalidParameterValueException;
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.StringUtils;
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);
        when(account.getType()).thenReturn(Account.Type.ADMIN);
        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() {
        List<Reserver> reservations = new ArrayList<>();
        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 (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
            resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template, reservations);
            List<String> tags = new ArrayList<>();
            tags.add(null);
            tags.add(hostTags.get(0));
            Assert.assertEquals(4, mockCheckedReservation.constructed().size());
        } catch (ResourceAllocationException e) {
            Assert.fail("Exception encountered: " + e.getMessage());
        }
    }

    @Test
    public void testCheckVolumeResourceLimit() {
        List<Reserver> reservations = new ArrayList<>();
        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 (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
            resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering, reservations);
            Assert.assertEquals(2, reservations.size());
        } 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(account.getDomainId()).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(1L, 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.when(projectVO.getDomainId()).thenReturn(1L);
        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(1L, 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());
        }
    }

    private ResourceCountVO mockCountRow(long id) {
        ResourceCountVO row = Mockito.mock(ResourceCountVO.class);
        Mockito.when(row.getId()).thenReturn(id);
        return row;
    }

    private ResourceLimitVO mockLimitRow(long domainId, long max) {
        ResourceLimitVO row = Mockito.mock(ResourceLimitVO.class);
        Mockito.when(row.getDomainId()).thenReturn(domainId);
        Mockito.when(row.getMax()).thenReturn(max);
        return row;
    }

    /**
     * Mocks domainDao.findById() so that walking getParent() from
     * chainWithRootLast[0] visits chainWithRootLast in order, ending at
     * Domain.ROOT_DOMAIN (the last element).
     */
    private void mockDomainParentChain(long... chainWithRootLast) {
        for (int i = 0; i < chainWithRootLast.length - 1; i++) {
            DomainVO domain = Mockito.mock(DomainVO.class);
            Mockito.when(domain.getParent()).thenReturn(chainWithRootLast[i + 1]);
            Mockito.when(domainDao.findById(chainWithRootLast[i])).thenReturn(domain);
        }
    }

    @Test
    public void testListRowsToLockForLimitCheckOnlyAccountDomainHasFiniteLimit() {
        // Account-domain has a finite limit; zone-domain (parent) has none (unlimited).
        // Expected lock set = {account row, account-domain row}.
        long accountId = 1L;
        long accountDomainId = 7L;
        long zoneDomainId = 3L;
        Resource.ResourceType type = Resource.ResourceType.volume;
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, zoneDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        ResourceCountVO accountDomainRow = mockCountRow(200L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, null))
                .thenReturn(accountRow);

        Set<Long> chainSet = new HashSet<>(Arrays.asList(accountDomainId, zoneDomainId));
        ResourceLimitVO accountDomainLimitRow = mockLimitRow(accountDomainId, 10L);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, null))
                .thenReturn(Collections.singletonList(accountDomainLimitRow));
        Mockito.when(resourceCountDao.findByOwnersAndTypeAndTag(Mockito.anyList(), Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.eq(type), Mockito.isNull()))
                .thenReturn(Collections.singletonList(accountDomainRow));

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, null);

        Assert.assertEquals(new HashSet<>(Arrays.asList(100L, 200L)), rowIds);
        Mockito.verify(resourceCountDao, Mockito.never()).listAllRowsToUpdate(Mockito.anyLong(), Mockito.any(), Mockito.any(), Mockito.any());
        Mockito.verify(resourceCountDao, Mockito.times(1))
                .findByOwnersAndTypeAndTag(Mockito.eq(Collections.singletonList(accountDomainId)), Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.eq(type), Mockito.isNull());
    }

    @Test
    public void testListRowsToLockForLimitCheckMultipleFiniteAncestors() {
        // Both ancestor-domain rows have finite limits; both must be locked.
        long accountId = 1L;
        long accountDomainId = 7L;
        long zoneDomainId = 3L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, zoneDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        ResourceCountVO accountDomainRow = mockCountRow(200L);
        ResourceCountVO zoneDomainRow = mockCountRow(300L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, null))
                .thenReturn(accountRow);

        Set<Long> chainSet = new HashSet<>(Arrays.asList(accountDomainId, zoneDomainId));
        ResourceLimitVO accountDomainLimitRow = mockLimitRow(accountDomainId, 10L);
        ResourceLimitVO zoneDomainLimitRow = mockLimitRow(zoneDomainId, 20L);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, null))
                .thenReturn(Arrays.asList(accountDomainLimitRow, zoneDomainLimitRow));
        Mockito.when(resourceCountDao.findByOwnersAndTypeAndTag(Mockito.anyList(), Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.eq(type), Mockito.isNull()))
                .thenReturn(Arrays.asList(accountDomainRow, zoneDomainRow));

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, null);

        Assert.assertEquals(new HashSet<>(Arrays.asList(100L, 200L, 300L)), rowIds);
    }

    @Test
    public void testListRowsToLockForLimitCheckInheritsFiniteLimitFromAncestorRow() {
        // Account-domain has NO explicit row of its own, but inherits a finite limit from
        // its parent (zone-domain)'s explicit row. Both must be locked: the zone-domain
        // because it owns the finite row, and the account-domain because its own effective
        // limit (via inheritance) is also finite.
        long accountId = 1L;
        long accountDomainId = 7L;
        long zoneDomainId = 3L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, zoneDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        ResourceCountVO accountDomainRow = mockCountRow(200L);
        ResourceCountVO zoneDomainRow = mockCountRow(300L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, null))
                .thenReturn(accountRow);

        Set<Long> chainSet = new HashSet<>(Arrays.asList(accountDomainId, zoneDomainId));
        // Only the zone-domain owns an explicit row; the account-domain has none.
        ResourceLimitVO zoneDomainLimitRow = mockLimitRow(zoneDomainId, 20L);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, null))
                .thenReturn(Collections.singletonList(zoneDomainLimitRow));
        Mockito.when(resourceCountDao.findByOwnersAndTypeAndTag(Mockito.anyList(), Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.eq(type), Mockito.isNull()))
                .thenReturn(Arrays.asList(accountDomainRow, zoneDomainRow));

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, null);

        Assert.assertEquals(new HashSet<>(Arrays.asList(100L, 200L, 300L)), rowIds);
    }

    @Test
    public void testListRowsToLockForLimitCheckAllUnlimited() {
        // No ancestor has a finite limit; only the account row is locked.
        long accountId = 1L;
        long accountDomainId = 7L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, null))
                .thenReturn(accountRow);

        Set<Long> chainSet = Collections.singleton(accountDomainId);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, null))
                .thenReturn(Collections.emptyList());

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, null);

        Assert.assertEquals(Collections.singleton(100L), rowIds);
        Mockito.verify(resourceCountDao, Mockito.never()).findByOwnersAndTypeAndTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
    }

    @Test
    public void testListRowsToLockForLimitCheckFiniteGlobalDefaultFallsBack() {
        // primary_storage with a finite global default → fall back to listAllRowsToUpdate
        // to preserve upstream behavior (every ancestor inherits the finite default).
        long accountId = 1L;
        Resource.ResourceType type = Resource.ResourceType.primary_storage;
        Set<Long> fullChain = new HashSet<>(Arrays.asList(100L, 200L, 300L, 400L));

        Mockito.doReturn(1024L).when(resourceLimitManager).findDefaultResourceLimitForDomain(type);
        Mockito.when(resourceCountDao.listAllRowsToUpdate(accountId, Resource.ResourceOwnerType.Account, type, null))
                .thenReturn(fullChain);

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, null);

        Assert.assertEquals(fullChain, rowIds);
        Mockito.verify(resourceLimitDao, Mockito.never()).listByDomainIdsAndTypeAndTag(Mockito.anySet(), Mockito.any(), Mockito.any());
    }

    @Test
    public void testListRowsToLockForLimitCheckTaggedAccountRowMissingFallsBack() {
        // Tagged limit, account row not yet materialized → fall back to listAllRowsToUpdate
        // so the create-on-miss tagged-row materialization still fires.
        long accountId = 1L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        String tag = hostTags.get(0);
        Set<Long> fullChain = new HashSet<>(Arrays.asList(101L, 201L));

        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, tag))
                .thenReturn(null);
        Mockito.when(resourceCountDao.listAllRowsToUpdate(accountId, Resource.ResourceOwnerType.Account, type, tag))
                .thenReturn(fullChain);

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, tag);

        Assert.assertEquals(fullChain, rowIds);
        Mockito.verify(resourceCountDao, Mockito.times(1)).listAllRowsToUpdate(accountId, Resource.ResourceOwnerType.Account, type, tag);
        Mockito.verify(resourceLimitDao, Mockito.never()).listByDomainIdsAndTypeAndTag(Mockito.anySet(), Mockito.any(), Mockito.any());
    }

    @Test
    public void testListRowsToLockForLimitCheckTagFallsBackToUntaggedWhenNoTagRowExists() {
        // No domain in the chain has ANY explicit tag-specific row, but the account-domain
        // has a finite UNTAGGED limit. findCorrectResourceLimitForDomain falls back to that
        // untagged limit for this domain, so it must still get its (tagged) resource_count
        // row locked.
        long accountId = 1L;
        long accountDomainId = 7L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        String tag = hostTags.get(0);
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        ResourceCountVO accountDomainRow = mockCountRow(200L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, tag))
                .thenReturn(accountRow);

        Set<Long> chainSet = Collections.singleton(accountDomainId);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, tag))
                .thenReturn(Collections.emptyList());
        ResourceLimitVO accountDomainLimitRow = mockLimitRow(accountDomainId, 10L);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, null))
                .thenReturn(Collections.singletonList(accountDomainLimitRow));
        Mockito.when(resourceCountDao.findByOwnersAndTypeAndTag(Mockito.eq(Collections.singletonList(accountDomainId)), Mockito.eq(Resource.ResourceOwnerType.Domain), Mockito.eq(type), Mockito.eq(tag)))
                .thenReturn(Collections.singletonList(accountDomainRow));

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, tag);

        Assert.assertEquals(new HashSet<>(Arrays.asList(100L, 200L)), rowIds);
    }

    @Test
    public void testListRowsToLockForLimitCheckExplicitUnlimitedTagRowSkipsUntaggedFallback() {
        // An explicit tag-specific row exists (even though it's UNLIMITED), so
        // findCorrectResourceLimitForDomain does NOT fall back to the untagged limit for
        // this domain. The untagged finite-limit lookup must never be consulted, and the
        // domain must not be locked.
        long accountId = 1L;
        long accountDomainId = 7L;
        Resource.ResourceType type = Resource.ResourceType.cpu;
        String tag = hostTags.get(0);
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getDomainId()).thenReturn(accountDomainId);
        Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
        mockDomainParentChain(accountDomainId, Domain.ROOT_DOMAIN);

        ResourceCountVO accountRow = mockCountRow(100L);
        Mockito.when(resourceCountDao.findByOwnerAndTypeAndTag(accountId, Resource.ResourceOwnerType.Account, type, tag))
                .thenReturn(accountRow);

        Set<Long> chainSet = Collections.singleton(accountDomainId);
        ResourceLimitVO unlimitedTagRow = mockLimitRow(accountDomainId, Resource.RESOURCE_UNLIMITED);
        Mockito.when(resourceLimitDao.listByDomainIdsAndTypeAndTag(chainSet, type, tag))
                .thenReturn(Collections.singletonList(unlimitedTagRow));

        Set<Long> rowIds = resourceLimitManager.listRowsToLockForLimitCheck(accountId, type, tag);

        Assert.assertEquals(Collections.singleton(100L), rowIds);
        Mockito.verify(resourceLimitDao, Mockito.never()).listByDomainIdsAndTypeAndTag(chainSet, type, null);
        Mockito.verify(resourceCountDao, Mockito.never()).findByOwnersAndTypeAndTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
    }

    @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 testRecalculateResourceCountRemovedAccount() {
        Long accountId = 10L;
        Long domainId = 2L;
        Resource.ResourceType type = Resource.ResourceType.secondary_storage;
        Mockito.when(domainDao.findById(domainId)).thenReturn(Mockito.mock(DomainVO.class));
        Account removedAccount = Mockito.mock(Account.class);
        Mockito.when(entityManager.findByIdIncludingRemoved(Account.class, accountId)).thenReturn(removedAccount);
        Mockito.doNothing().when(resourceLimitManager).removeResourceLimitAndCountForNonMatchingTags(Mockito.anyLong(),
                Mockito.any(), Mockito.anyList(), Mockito.anyList());
        Mockito.doReturn(1L).when(resourceLimitManager).recalculateAccountResourceCount(accountId, type, null);
        Mockito.doReturn(new ArrayList<>()).when(resourceLimitManager).recalculateAccountTaggedResourceCount(
                Mockito.eq(accountId.longValue()), Mockito.eq(type), Mockito.anyList(), Mockito.anyList());

        List<? extends ResourceCount> result = resourceLimitManager.recalculateResourceCount(accountId, domainId, type.getOrdinal(), null);

        Assert.assertEquals(1, result.size());
        Mockito.verify(accountManager).verifyCallerPrivilegeForUserOrAccountOperations(removedAccount);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testRecalculateResourceCountAccountNotFound() {
        Long accountId = 10L;
        Long domainId = 2L;
        Mockito.when(domainDao.findById(domainId)).thenReturn(Mockito.mock(DomainVO.class));
        Mockito.when(entityManager.findByIdIncludingRemoved(Account.class, accountId)).thenReturn(null);
        resourceLimitManager.recalculateResourceCount(accountId, domainId, Resource.ResourceType.secondary_storage.getOrdinal(), 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 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 {
        List<Reserver> reservations = new ArrayList<>();
        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), Mockito.any());
        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), Mockito.any());

        try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
            resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class), reservations);
            Assert.assertEquals(2,  reservations.size());
        }
    }

    @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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        resourceLimitManager.decrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class), null);
        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), Mockito.any());
        mockDecrementResourceCountWithTag();
        resourceLimitManager.decrementVolumeResourceCount(accountId, false, delta, Mockito.mock(DiskOffering.class), null);
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        resourceLimitManager.incrementVmResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        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), Mockito.any());
        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), null);
        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), Mockito.any());
        resourceLimitManager.decrementVmResourceCount(accountId, false,
                Mockito.mock(ServiceOffering.class), Mockito.mock(VirtualMachineTemplate.class), null);
        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), Mockito.any());
        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), null);
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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), Mockito.any());
        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());
    }
}
