001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.quotas; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertTrue; 022import static org.mockito.Mockito.doNothing; 023import static org.mockito.Mockito.doThrow; 024import static org.mockito.Mockito.mock; 025import static org.mockito.Mockito.when; 026 027import java.io.IOException; 028import java.util.HashMap; 029import java.util.Map; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot.SpaceQuotaStatus; 032import org.apache.hadoop.hbase.quotas.policies.DefaultViolationPolicyEnforcement; 033import org.apache.hadoop.hbase.quotas.policies.DisableTableViolationPolicyEnforcement; 034import org.apache.hadoop.hbase.quotas.policies.NoInsertsViolationPolicyEnforcement; 035import org.apache.hadoop.hbase.quotas.policies.NoWritesCompactionsViolationPolicyEnforcement; 036import org.apache.hadoop.hbase.quotas.policies.NoWritesViolationPolicyEnforcement; 037import org.apache.hadoop.hbase.regionserver.RegionServerServices; 038import org.apache.hadoop.hbase.testclassification.SmallTests; 039import org.junit.jupiter.api.BeforeEach; 040import org.junit.jupiter.api.Tag; 041import org.junit.jupiter.api.Test; 042 043/** 044 * Test class for {@link RegionServerSpaceQuotaManager}. 045 */ 046@Tag(SmallTests.TAG) 047public class TestRegionServerSpaceQuotaManager { 048 049 private RegionServerSpaceQuotaManager quotaManager; 050 private RegionServerServices rss; 051 052 @BeforeEach 053 public void setup() throws Exception { 054 quotaManager = mock(RegionServerSpaceQuotaManager.class); 055 rss = mock(RegionServerServices.class); 056 } 057 058 @Test 059 public void testSpacePoliciesFromEnforcements() { 060 final Map<TableName, SpaceViolationPolicyEnforcement> enforcements = new HashMap<>(); 061 final Map<TableName, SpaceQuotaSnapshot> expectedPolicies = new HashMap<>(); 062 when(quotaManager.copyActiveEnforcements()).thenReturn(enforcements); 063 when(quotaManager.getActivePoliciesAsMap()).thenCallRealMethod(); 064 065 NoInsertsViolationPolicyEnforcement noInsertsPolicy = new NoInsertsViolationPolicyEnforcement(); 066 SpaceQuotaSnapshot noInsertsSnapshot = 067 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 256L, 1024L); 068 noInsertsPolicy.initialize(rss, TableName.valueOf("no_inserts"), noInsertsSnapshot); 069 enforcements.put(noInsertsPolicy.getTableName(), noInsertsPolicy); 070 expectedPolicies.put(noInsertsPolicy.getTableName(), noInsertsSnapshot); 071 072 NoWritesViolationPolicyEnforcement noWritesPolicy = new NoWritesViolationPolicyEnforcement(); 073 SpaceQuotaSnapshot noWritesSnapshot = 074 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES), 512L, 2048L); 075 noWritesPolicy.initialize(rss, TableName.valueOf("no_writes"), noWritesSnapshot); 076 enforcements.put(noWritesPolicy.getTableName(), noWritesPolicy); 077 expectedPolicies.put(noWritesPolicy.getTableName(), noWritesSnapshot); 078 079 NoWritesCompactionsViolationPolicyEnforcement noWritesCompactionsPolicy = 080 new NoWritesCompactionsViolationPolicyEnforcement(); 081 SpaceQuotaSnapshot noWritesCompactionsSnapshot = new SpaceQuotaSnapshot( 082 new SpaceQuotaStatus(SpaceViolationPolicy.NO_WRITES_COMPACTIONS), 1024L, 4096L); 083 noWritesCompactionsPolicy.initialize(rss, TableName.valueOf("no_writes_compactions"), 084 noWritesCompactionsSnapshot); 085 enforcements.put(noWritesCompactionsPolicy.getTableName(), noWritesCompactionsPolicy); 086 expectedPolicies.put(noWritesCompactionsPolicy.getTableName(), noWritesCompactionsSnapshot); 087 088 DisableTableViolationPolicyEnforcement disablePolicy = 089 new DisableTableViolationPolicyEnforcement(); 090 SpaceQuotaSnapshot disableSnapshot = 091 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 2048L, 8192L); 092 disablePolicy.initialize(rss, TableName.valueOf("disable"), disableSnapshot); 093 enforcements.put(disablePolicy.getTableName(), disablePolicy); 094 expectedPolicies.put(disablePolicy.getTableName(), disableSnapshot); 095 096 enforcements.put(TableName.valueOf("no_policy"), new DefaultViolationPolicyEnforcement()); 097 098 Map<TableName, SpaceQuotaSnapshot> actualPolicies = quotaManager.getActivePoliciesAsMap(); 099 assertEquals(expectedPolicies, actualPolicies); 100 } 101 102 @Test 103 public void testExceptionOnPolicyEnforcementEnable() throws Exception { 104 final TableName tableName = TableName.valueOf("foo"); 105 final SpaceQuotaSnapshot snapshot = 106 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 1024L, 2048L); 107 RegionServerServices rss = mock(RegionServerServices.class); 108 SpaceViolationPolicyEnforcementFactory factory = 109 mock(SpaceViolationPolicyEnforcementFactory.class); 110 SpaceViolationPolicyEnforcement enforcement = mock(SpaceViolationPolicyEnforcement.class); 111 RegionServerSpaceQuotaManager realManager = new RegionServerSpaceQuotaManager(rss, factory); 112 113 when(factory.create(rss, tableName, snapshot)).thenReturn(enforcement); 114 doThrow(new IOException("Failed for test!")).when(enforcement).enable(); 115 116 realManager.enforceViolationPolicy(tableName, snapshot); 117 Map<TableName, SpaceViolationPolicyEnforcement> enforcements = 118 realManager.copyActiveEnforcements(); 119 assertTrue(enforcements.isEmpty(), 120 "Expected active enforcements to be empty, but were " + enforcements); 121 } 122 123 @Test 124 public void testExceptionOnPolicyEnforcementDisable() throws Exception { 125 final TableName tableName = TableName.valueOf("foo"); 126 final SpaceQuotaSnapshot snapshot = 127 new SpaceQuotaSnapshot(new SpaceQuotaStatus(SpaceViolationPolicy.DISABLE), 1024L, 2048L); 128 RegionServerServices rss = mock(RegionServerServices.class); 129 SpaceViolationPolicyEnforcementFactory factory = 130 mock(SpaceViolationPolicyEnforcementFactory.class); 131 SpaceViolationPolicyEnforcement enforcement = mock(SpaceViolationPolicyEnforcement.class); 132 RegionServerSpaceQuotaManager realManager = new RegionServerSpaceQuotaManager(rss, factory); 133 134 when(factory.create(rss, tableName, snapshot)).thenReturn(enforcement); 135 doNothing().when(enforcement).enable(); 136 doThrow(new IOException("Failed for test!")).when(enforcement).disable(); 137 138 // Enabling should work 139 realManager.enforceViolationPolicy(tableName, snapshot); 140 Map<TableName, SpaceViolationPolicyEnforcement> enforcements = 141 realManager.copyActiveEnforcements(); 142 assertEquals(1, enforcements.size()); 143 144 // If the disable fails, we should still treat it as "active" 145 realManager.disableViolationPolicyEnforcement(tableName); 146 enforcements = realManager.copyActiveEnforcements(); 147 assertEquals(1, enforcements.size()); 148 } 149}