1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.quotas;
18
19 import static org.mockito.Matchers.argThat;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.verify;
22 import static org.mockito.Mockito.when;
23
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.Map.Entry;
27 import java.util.NavigableMap;
28 import java.util.Objects;
29
30 import org.apache.hadoop.hbase.Cell;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.client.Connection;
33 import org.apache.hadoop.hbase.client.Mutation;
34 import org.apache.hadoop.hbase.client.Put;
35 import org.apache.hadoop.hbase.client.Table;
36 import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot.SpaceQuotaStatus;
37 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
38 import org.apache.hadoop.hbase.testclassification.SmallTests;
39 import org.apache.hadoop.hbase.util.Bytes;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.experimental.categories.Category;
43 import org.mockito.ArgumentMatcher;
44
45
46
47
48 @Category(SmallTests.class)
49 public class TestTableSpaceQuotaViolationNotifier {
50
51 private TableSpaceQuotaSnapshotNotifier notifier;
52 private Connection conn;
53
54 @Before
55 public void setup() throws Exception {
56 notifier = new TableSpaceQuotaSnapshotNotifier();
57 conn = mock(Connection.class);
58 notifier.initialize(conn);
59 }
60
61 @Test
62 public void testToViolation() throws Exception {
63 final TableName tn = TableName.valueOf("inviolation");
64 final SpaceQuotaSnapshot snapshot = new SpaceQuotaSnapshot(
65 new SpaceQuotaStatus(SpaceViolationPolicy.NO_INSERTS), 1024L, 512L);
66 final Table quotaTable = mock(Table.class);
67 when(conn.getTable(QuotaTableUtil.QUOTA_TABLE_NAME)).thenReturn(quotaTable);
68
69 final Put expectedPut = new Put(Bytes.toBytes("t." + tn.getNameAsString()));
70 final QuotaProtos.SpaceQuotaSnapshot protoQuota = QuotaProtos.SpaceQuotaSnapshot.newBuilder()
71 .setQuotaStatus(QuotaProtos.SpaceQuotaStatus.newBuilder().setInViolation(true)
72 .setViolationPolicy(QuotaProtos.SpaceViolationPolicy.NO_INSERTS))
73 .setQuotaLimit(512L)
74 .setQuotaUsage(1024L)
75 .build();
76 expectedPut.addColumn(Bytes.toBytes("u"), Bytes.toBytes("p"), protoQuota.toByteArray());
77
78 notifier.transitionTable(tn, snapshot);
79
80 verify(quotaTable).put(argThat(new SingleCellPutMatcher(expectedPut)));
81 }
82
83
84
85
86 private static class SingleCellPutMatcher extends SingleCellMutationMatcher<Put> {
87 private SingleCellPutMatcher(Put expected) {
88 super(expected);
89 }
90 }
91
92
93
94
95 private static class SingleCellMutationMatcher<T> extends ArgumentMatcher<T> {
96 private final Mutation expected;
97
98 private SingleCellMutationMatcher(Mutation expected) {
99 this.expected = expected;
100 }
101
102 @Override
103 public boolean matches(Object argument) {
104 if (!expected.getClass().isAssignableFrom(argument.getClass())) {
105 return false;
106 }
107 Mutation actual = (Mutation) argument;
108 if (!Arrays.equals(expected.getRow(), actual.getRow())) {
109 return false;
110 }
111 if (expected.size() != actual.size()) {
112 return false;
113 }
114 NavigableMap<byte[],List<Cell>> expectedCells = expected.getFamilyCellMap();
115 NavigableMap<byte[],List<Cell>> actualCells = actual.getFamilyCellMap();
116 Entry<byte[],List<Cell>> expectedEntry = expectedCells.entrySet().iterator().next();
117 Entry<byte[],List<Cell>> actualEntry = actualCells.entrySet().iterator().next();
118 if (!Arrays.equals(expectedEntry.getKey(), actualEntry.getKey())) {
119 return false;
120 }
121 return Objects.equals(expectedEntry.getValue(), actualEntry.getValue());
122 }
123 }
124 }