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.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertNotNull;
023import static org.junit.Assert.fail;
024
025import java.io.IOException;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.TableName;
028import org.apache.hadoop.hbase.testclassification.SmallTests;
029import org.junit.ClassRule;
030import org.junit.Test;
031import org.junit.experimental.categories.Category;
032
033import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
034import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
035import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceLimitRequest;
036import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceQuota;
037
038/**
039 * Test class for {@link SpaceLimitSettings}.
040 */
041@Category({ SmallTests.class })
042public class TestSpaceLimitSettings {
043
044  @ClassRule
045  public static final HBaseClassTestRule CLASS_RULE =
046    HBaseClassTestRule.forClass(TestSpaceLimitSettings.class);
047
048  @Test(expected = IllegalArgumentException.class)
049  public void testInvalidTableQuotaSizeLimit() {
050    new SpaceLimitSettings(TableName.valueOf("foo"), -1, SpaceViolationPolicy.NO_INSERTS);
051  }
052
053  @Test(expected = NullPointerException.class)
054  public void testNullTableName() {
055    TableName tn = null;
056    new SpaceLimitSettings(tn, 1, SpaceViolationPolicy.NO_INSERTS);
057  }
058
059  @Test(expected = NullPointerException.class)
060  public void testNullTableViolationPolicy() {
061    new SpaceLimitSettings(TableName.valueOf("foo"), 1, null);
062  }
063
064  @Test(expected = IllegalArgumentException.class)
065  public void testInvalidNamespaceQuotaSizeLimit() {
066    new SpaceLimitSettings("foo_ns", -1, SpaceViolationPolicy.NO_INSERTS);
067  }
068
069  @Test(expected = NullPointerException.class)
070  public void testNullNamespace() {
071    String ns = null;
072    new SpaceLimitSettings(ns, 1, SpaceViolationPolicy.NO_INSERTS);
073  }
074
075  @Test(expected = NullPointerException.class)
076  public void testNullNamespaceViolationPolicy() {
077    new SpaceLimitSettings("foo_ns", 1, null);
078  }
079
080  @Test
081  public void testTableQuota() {
082    final TableName tableName = TableName.valueOf("foo");
083    final long sizeLimit = 1024 * 1024;
084    final SpaceViolationPolicy policy = SpaceViolationPolicy.NO_WRITES;
085    SpaceLimitSettings settings = new SpaceLimitSettings(tableName, sizeLimit, policy);
086    SetQuotaRequest proto = QuotaSettings.buildSetQuotaRequestProto(settings);
087
088    assertFalse("User should be missing", proto.hasUserName());
089    assertFalse("Namespace should be missing", proto.hasNamespace());
090    assertEquals(ProtobufUtil.toProtoTableName(tableName), proto.getTableName());
091    SpaceLimitRequest spaceLimitReq = proto.getSpaceLimit();
092    assertNotNull("SpaceLimitRequest was null", spaceLimitReq);
093    SpaceQuota spaceQuota = spaceLimitReq.getQuota();
094    assertNotNull("SpaceQuota was null", spaceQuota);
095    assertEquals(sizeLimit, spaceQuota.getSoftLimit());
096    assertEquals(ProtobufUtil.toProtoViolationPolicy(policy), spaceQuota.getViolationPolicy());
097
098    assertEquals(QuotaType.SPACE, settings.getQuotaType());
099
100    SpaceLimitSettings copy = new SpaceLimitSettings(tableName, sizeLimit, policy);
101    assertEquals(settings, copy);
102    assertEquals(settings.hashCode(), copy.hashCode());
103  }
104
105  @Test
106  public void testNamespaceQuota() {
107    final String namespace = "foo_ns";
108    final long sizeLimit = 1024 * 1024;
109    final SpaceViolationPolicy policy = SpaceViolationPolicy.NO_WRITES;
110    SpaceLimitSettings settings = new SpaceLimitSettings(namespace, sizeLimit, policy);
111    SetQuotaRequest proto = QuotaSettings.buildSetQuotaRequestProto(settings);
112
113    assertFalse("User should be missing", proto.hasUserName());
114    assertFalse("TableName should be missing", proto.hasTableName());
115    assertEquals(namespace, proto.getNamespace());
116    SpaceLimitRequest spaceLimitReq = proto.getSpaceLimit();
117    assertNotNull("SpaceLimitRequest was null", spaceLimitReq);
118    SpaceQuota spaceQuota = spaceLimitReq.getQuota();
119    assertNotNull("SpaceQuota was null", spaceQuota);
120    assertEquals(sizeLimit, spaceQuota.getSoftLimit());
121    assertEquals(ProtobufUtil.toProtoViolationPolicy(policy), spaceQuota.getViolationPolicy());
122
123    assertEquals(QuotaType.SPACE, settings.getQuotaType());
124
125    SpaceLimitSettings copy = new SpaceLimitSettings(namespace, sizeLimit, policy);
126    assertEquals(settings, copy);
127    assertEquals(settings.hashCode(), copy.hashCode());
128  }
129
130  @Test
131  public void testQuotaMerging() throws IOException {
132    TableName tn = TableName.valueOf("foo");
133    QuotaSettings originalSettings =
134      QuotaSettingsFactory.limitTableSpace(tn, 1024L * 1024L, SpaceViolationPolicy.DISABLE);
135    QuotaSettings largerSizeLimit =
136      QuotaSettingsFactory.limitTableSpace(tn, 5L * 1024L * 1024L, SpaceViolationPolicy.DISABLE);
137    QuotaSettings differentPolicy =
138      QuotaSettingsFactory.limitTableSpace(tn, 1024L * 1024L, SpaceViolationPolicy.NO_WRITES);
139    QuotaSettings incompatibleSettings = QuotaSettingsFactory.limitNamespaceSpace("ns1",
140      5L * 1024L * 1024L, SpaceViolationPolicy.NO_WRITES);
141
142    assertEquals(originalSettings.merge(largerSizeLimit), largerSizeLimit);
143    assertEquals(originalSettings.merge(differentPolicy), differentPolicy);
144    try {
145      originalSettings.merge(incompatibleSettings);
146      fail("Should not be able to merge a Table space quota with a namespace space quota.");
147    } catch (IllegalArgumentException e) {
148      // pass
149    }
150  }
151}