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.hbtop; 019 020import static org.hamcrest.CoreMatchers.hasItems; 021import static org.hamcrest.CoreMatchers.is; 022import static org.hamcrest.CoreMatchers.notNullValue; 023import static org.hamcrest.CoreMatchers.nullValue; 024import static org.junit.Assert.assertThat; 025 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.Collections; 029import java.util.List; 030import java.util.stream.Collectors; 031import org.apache.hadoop.hbase.HBaseClassTestRule; 032import org.apache.hadoop.hbase.Size; 033import org.apache.hadoop.hbase.hbtop.field.Field; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.junit.ClassRule; 036import org.junit.Test; 037import org.junit.experimental.categories.Category; 038 039 040@Category(SmallTests.class) 041public class TestRecordFilter { 042 043 @ClassRule 044 public static final HBaseClassTestRule CLASS_RULE = 045 HBaseClassTestRule.forClass(TestRecordFilter.class); 046 047 @Test 048 public void testParseAndBuilder() { 049 testParseAndBuilder("REGION=region1", false, 050 RecordFilter.newBuilder(Field.REGION).equal("region1")); 051 052 testParseAndBuilder("REGION=", false, 053 RecordFilter.newBuilder(Field.REGION).equal("")); 054 055 testParseAndBuilder("!REGION=region1", false, 056 RecordFilter.newBuilder(Field.REGION).notEqual("region1")); 057 058 testParseAndBuilder("REGION==region2", true, 059 RecordFilter.newBuilder(Field.REGION, true).doubleEquals("region2")); 060 061 testParseAndBuilder("!REGION==region2", true, 062 RecordFilter.newBuilder(Field.REGION, true).notDoubleEquals("region2")); 063 064 testParseAndBuilder("#REQ/S>100", false, 065 RecordFilter.newBuilder(Field.REQUEST_COUNT_PER_SECOND).greater(100L)); 066 067 testParseAndBuilder("!#REQ/S>100", false, 068 RecordFilter.newBuilder(Field.REQUEST_COUNT_PER_SECOND).notGreater(100L)); 069 070 testParseAndBuilder("SF>=50MB", true, 071 RecordFilter.newBuilder(Field.STORE_FILE_SIZE, true).greaterOrEqual("50MB")); 072 073 testParseAndBuilder("!SF>=50MB", true, 074 RecordFilter.newBuilder(Field.STORE_FILE_SIZE, true).notGreaterOrEqual("50MB")); 075 076 testParseAndBuilder("#REQ/S<20", false, 077 RecordFilter.newBuilder(Field.REQUEST_COUNT_PER_SECOND).less(20L)); 078 079 testParseAndBuilder("!#REQ/S<20", false, 080 RecordFilter.newBuilder(Field.REQUEST_COUNT_PER_SECOND).notLess(20L)); 081 082 testParseAndBuilder("%COMP<=50%", true, 083 RecordFilter.newBuilder(Field.COMPACTION_PROGRESS, true).lessOrEqual("50%")); 084 085 testParseAndBuilder("!%COMP<=50%", true, 086 RecordFilter.newBuilder(Field.COMPACTION_PROGRESS, true).notLessOrEqual("50%")); 087 } 088 089 private void testParseAndBuilder(String filterString, boolean ignoreCase, RecordFilter expected) { 090 RecordFilter actual = RecordFilter.parse(filterString, ignoreCase); 091 assertThat(expected, is(actual)); 092 } 093 094 @Test 095 public void testParseFailure() { 096 RecordFilter filter = RecordFilter.parse("REGIO=region1", false); 097 assertThat(filter, is(nullValue())); 098 099 filter = RecordFilter.parse("", false); 100 assertThat(filter, is(nullValue())); 101 102 filter = RecordFilter.parse("#REQ/S==aaa", false); 103 assertThat(filter, is(nullValue())); 104 105 filter = RecordFilter.parse("SF>=50", false); 106 assertThat(filter, is(nullValue())); 107 } 108 109 @Test 110 public void testToString() { 111 testToString("REGION=region1"); 112 testToString("!REGION=region1"); 113 testToString("REGION==region2"); 114 testToString("!REGION==region2"); 115 testToString("#REQ/S>100"); 116 testToString("!#REQ/S>100"); 117 testToString("SF>=50.0MB"); 118 testToString("!SF>=50.0MB"); 119 testToString("#REQ/S<20"); 120 testToString("!#REQ/S<20"); 121 testToString("%COMP<=50.00%"); 122 testToString("!%COMP<=50.00%"); 123 } 124 125 private void testToString(String filterString) { 126 RecordFilter filter = RecordFilter.parse(filterString, false); 127 assertThat(filter, is(notNullValue())); 128 assertThat(filterString, is(filter.toString())); 129 } 130 131 @Test 132 public void testFilters() { 133 List<Record> records = createTestRecords(); 134 135 testFilter(records, "REGION=region", false, 136 "region1", "region2", "region3", "region4", "region5"); 137 testFilter(records, "!REGION=region", false); 138 testFilter(records, "REGION=Region", false); 139 140 testFilter(records, "REGION==region", false); 141 testFilter(records, "REGION==region1", false, "region1"); 142 testFilter(records, "!REGION==region1", false, "region2", "region3", "region4", "region5"); 143 144 testFilter(records, "#REQ/S==100", false, "region1"); 145 testFilter(records, "#REQ/S>100", false, "region2", "region5"); 146 testFilter(records, "SF>=100MB", false, "region1", "region2", "region4", "region5"); 147 testFilter(records, "!#SF>=10", false, "region1", "region4"); 148 testFilter(records, "LOCALITY<0.5", false, "region5"); 149 testFilter(records, "%COMP<=50%", false, "region2", "region3", "region4", "region5"); 150 151 testFilters(records, Arrays.asList("SF>=100MB", "#REQ/S>100"), false, 152 "region2", "region5"); 153 testFilters(records, Arrays.asList("%COMP<=50%", "!#SF>=10"), false, "region4"); 154 testFilters(records, Arrays.asList("!REGION==region1", "LOCALITY<0.5", "#REQ/S>100"), false, 155 "region5"); 156 } 157 158 @Test 159 public void testFiltersIgnoreCase() { 160 List<Record> records = createTestRecords(); 161 162 testFilter(records, "REGION=Region", true, 163 "region1", "region2", "region3", "region4", "region5"); 164 testFilter(records, "REGION=REGION", true, 165 "region1", "region2", "region3", "region4", "region5"); 166 } 167 168 private List<Record> createTestRecords() { 169 List<Record> ret = new ArrayList<>(); 170 ret.add(createTestRecord("region1", 100L, new Size(100, Size.Unit.MEGABYTE), 2, 1.0f, 80f)); 171 ret.add(createTestRecord("region2", 120L, new Size(100, Size.Unit.GIGABYTE), 10, 0.5f, 20f)); 172 ret.add(createTestRecord("region3", 50L, new Size(500, Size.Unit.KILOBYTE), 15, 0.8f, 50f)); 173 ret.add(createTestRecord("region4", 90L, new Size(10, Size.Unit.TERABYTE), 5, 0.9f, 30f)); 174 ret.add(createTestRecord("region5", 200L, new Size(1, Size.Unit.PETABYTE), 13, 0.1f, 40f)); 175 return ret; 176 } 177 178 private Record createTestRecord(String region, long requestCountPerSecond, 179 Size storeFileSize, int numStoreFiles, float locality, float compactionProgress) { 180 Record.Builder builder = Record.builder(); 181 builder.put(Field.REGION, region); 182 builder.put(Field.REQUEST_COUNT_PER_SECOND, requestCountPerSecond); 183 builder.put(Field.STORE_FILE_SIZE, storeFileSize); 184 builder.put(Field.NUM_STORE_FILES, numStoreFiles); 185 builder.put(Field.LOCALITY, locality); 186 builder.put(Field.COMPACTION_PROGRESS, compactionProgress); 187 return builder.build(); 188 } 189 190 private void testFilter(List<Record> records, String filterString, boolean ignoreCase, 191 String... expectedRegions) { 192 testFilters(records, Collections.singletonList(filterString), ignoreCase, expectedRegions); 193 } 194 195 private void testFilters(List<Record> records, List<String> filterStrings, boolean ignoreCase, 196 String... expectedRegions) { 197 List<String> actual = 198 records.stream().filter(r -> filterStrings.stream() 199 .map(f -> RecordFilter.parse(f, ignoreCase)) 200 .allMatch(f -> f.execute(r))) 201 .map(r -> r.get(Field.REGION).asString()) 202 .collect(Collectors.toList()); 203 assertThat(actual, hasItems(expectedRegions)); 204 assertThat(actual.size(), is(expectedRegions.length)); 205 } 206}