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.screen.top; 019 020import static org.apache.hadoop.hbase.hbtop.Record.entry; 021import static org.mockito.ArgumentMatchers.any; 022import static org.mockito.ArgumentMatchers.argThat; 023import static org.mockito.Mockito.inOrder; 024import static org.mockito.Mockito.verify; 025import static org.mockito.Mockito.when; 026 027import java.util.Arrays; 028import java.util.List; 029import java.util.stream.Collectors; 030import org.apache.hadoop.hbase.HBaseClassTestRule; 031import org.apache.hadoop.hbase.hbtop.Record; 032import org.apache.hadoop.hbase.hbtop.field.Field; 033import org.apache.hadoop.hbase.hbtop.field.FieldInfo; 034import org.apache.hadoop.hbase.hbtop.terminal.TerminalSize; 035import org.apache.hadoop.hbase.testclassification.SmallTests; 036import org.junit.Before; 037import org.junit.ClassRule; 038import org.junit.Test; 039import org.junit.experimental.categories.Category; 040import org.junit.runner.RunWith; 041import org.mockito.InOrder; 042import org.mockito.Mock; 043import org.mockito.runners.MockitoJUnitRunner; 044 045 046@Category(SmallTests.class) 047@RunWith(MockitoJUnitRunner.class) 048public class TestTopScreenPresenter { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestTopScreenPresenter.class); 053 054 private static final List<FieldInfo> TEST_FIELD_INFOS = Arrays.asList( 055 new FieldInfo(Field.REGION, 10, true), 056 new FieldInfo(Field.REQUEST_COUNT_PER_SECOND, 10, true), 057 new FieldInfo(Field.LOCALITY, 10, true) 058 ); 059 060 private static final List<Record> TEST_RECORDS = Arrays.asList( 061 Record.ofEntries( 062 entry(Field.REGION, "region1"), 063 entry(Field.REQUEST_COUNT_PER_SECOND, 1L), 064 entry(Field.LOCALITY, 0.3f)), 065 Record.ofEntries( 066 entry(Field.REGION, "region2"), 067 entry(Field.REQUEST_COUNT_PER_SECOND, 2L), 068 entry(Field.LOCALITY, 0.2f)), 069 Record.ofEntries( 070 entry(Field.REGION, "region3"), 071 entry(Field.REQUEST_COUNT_PER_SECOND, 3L), 072 entry(Field.LOCALITY, 0.1f)) 073 ); 074 075 private static final Summary TEST_SUMMARY = new Summary( 076 "00:00:01", "3.0.0-SNAPSHOT", "01234567-89ab-cdef-0123-456789abcdef", 077 3, 2, 1, 6, 1, 3.0, 300); 078 079 @Mock 080 private TopScreenView topScreenView; 081 082 @Mock 083 private TopScreenModel topScreenModel; 084 085 private TopScreenPresenter topScreenPresenter; 086 087 @Before 088 public void setup() { 089 when(topScreenView.getTerminalSize()).thenReturn(new TerminalSize(100, 100)); 090 when(topScreenView.getPageSize()).thenReturn(100); 091 092 when(topScreenModel.getFieldInfos()).thenReturn(TEST_FIELD_INFOS); 093 when(topScreenModel.getFields()).thenReturn(TEST_FIELD_INFOS.stream() 094 .map(FieldInfo::getField).collect(Collectors.toList())); 095 when(topScreenModel.getRecords()).thenReturn(TEST_RECORDS); 096 when(topScreenModel.getSummary()).thenReturn(TEST_SUMMARY); 097 098 topScreenPresenter = new TopScreenPresenter(topScreenView, 3000, topScreenModel, 099 null, Long.MAX_VALUE); 100 } 101 102 @Test 103 public void testRefresh() { 104 topScreenPresenter.init(); 105 topScreenPresenter.refresh(true); 106 107 verify(topScreenView).showTopScreen(argThat(this::assertSummary), 108 argThat(this::assertHeaders), argThat(this::assertRecords), 109 argThat(selectedRecord -> assertSelectedRecord(selectedRecord, 0))); 110 } 111 112 @Test 113 public void testVerticalScrolling() { 114 topScreenPresenter.init(); 115 topScreenPresenter.refresh(true); 116 117 topScreenPresenter.arrowDown(); 118 topScreenPresenter.arrowDown(); 119 topScreenPresenter.arrowDown(); 120 121 topScreenPresenter.arrowDown(); 122 topScreenPresenter.arrowDown(); 123 topScreenPresenter.arrowDown(); 124 125 topScreenPresenter.arrowUp(); 126 topScreenPresenter.arrowUp(); 127 topScreenPresenter.arrowUp(); 128 129 topScreenPresenter.pageDown(); 130 topScreenPresenter.pageDown(); 131 132 topScreenPresenter.pageUp(); 133 topScreenPresenter.pageUp(); 134 135 InOrder inOrder = inOrder(topScreenView); 136 verifyVerticalScrolling(inOrder, 0); 137 138 verifyVerticalScrolling(inOrder, 1); 139 verifyVerticalScrolling(inOrder, 2); 140 verifyVerticalScrolling(inOrder, 2); 141 142 verifyVerticalScrolling(inOrder, 1); 143 verifyVerticalScrolling(inOrder, 0); 144 verifyVerticalScrolling(inOrder, 0); 145 146 verifyVerticalScrolling(inOrder, 2); 147 verifyVerticalScrolling(inOrder, 2); 148 149 verifyVerticalScrolling(inOrder, 0); 150 verifyVerticalScrolling(inOrder, 0); 151 } 152 153 private void verifyVerticalScrolling(InOrder inOrder, int expectedSelectedRecodeIndex) { 154 inOrder.verify(topScreenView).showTopScreen(any(), any(), any(), 155 argThat(selectedRecord -> assertSelectedRecord(selectedRecord, expectedSelectedRecodeIndex))); 156 } 157 158 @Test 159 public void testHorizontalScrolling() { 160 topScreenPresenter.init(); 161 topScreenPresenter.refresh(true); 162 163 topScreenPresenter.arrowRight(); 164 topScreenPresenter.arrowRight(); 165 topScreenPresenter.arrowRight(); 166 167 topScreenPresenter.arrowLeft(); 168 topScreenPresenter.arrowLeft(); 169 topScreenPresenter.arrowLeft(); 170 171 topScreenPresenter.end(); 172 topScreenPresenter.end(); 173 174 topScreenPresenter.home(); 175 topScreenPresenter.home(); 176 177 InOrder inOrder = inOrder(topScreenView); 178 verifyHorizontalScrolling(inOrder, 3); 179 180 verifyHorizontalScrolling(inOrder, 2); 181 verifyHorizontalScrolling(inOrder, 1); 182 verifyHorizontalScrolling(inOrder, 1); 183 184 verifyHorizontalScrolling(inOrder, 2); 185 verifyHorizontalScrolling(inOrder, 3); 186 verifyHorizontalScrolling(inOrder, 3); 187 188 verifyHorizontalScrolling(inOrder, 1); 189 verifyHorizontalScrolling(inOrder, 1); 190 191 verifyHorizontalScrolling(inOrder, 3); 192 verifyHorizontalScrolling(inOrder, 3); 193 } 194 195 private void verifyHorizontalScrolling(InOrder inOrder, int expectedHeaderCount) { 196 inOrder.verify(topScreenView).showTopScreen(any(), 197 argThat(headers -> headers.size() == expectedHeaderCount), any(), any()); 198 } 199 200 private boolean assertSummary(Summary actual) { 201 return actual.getCurrentTime().equals(TEST_SUMMARY.getCurrentTime()) 202 && actual.getVersion().equals(TEST_SUMMARY.getVersion()) 203 && actual.getClusterId().equals(TEST_SUMMARY.getClusterId()) 204 && actual.getServers() == TEST_SUMMARY.getServers() 205 && actual.getLiveServers() == TEST_SUMMARY.getLiveServers() 206 && actual.getDeadServers() == TEST_SUMMARY.getDeadServers() 207 && actual.getRegionCount() == TEST_SUMMARY.getRegionCount() 208 && actual.getRitCount() == TEST_SUMMARY.getRitCount() 209 && actual.getAverageLoad() == TEST_SUMMARY.getAverageLoad() 210 && actual.getAggregateRequestPerSecond() == TEST_SUMMARY.getAggregateRequestPerSecond(); 211 } 212 213 private boolean assertHeaders(List<Header> actual) { 214 List<Header> expected = 215 TEST_FIELD_INFOS.stream().map(fi -> new Header(fi.getField(), fi.getDefaultLength())) 216 .collect(Collectors.toList()); 217 218 if (actual.size() != expected.size()) { 219 return false; 220 } 221 222 for (int i = 0; i < actual.size(); i++) { 223 if (actual.get(i).getField() != expected.get(i).getField()) { 224 return false; 225 } 226 if (actual.get(i).getLength() != expected.get(i).getLength()) { 227 return false; 228 } 229 } 230 231 return true; 232 } 233 234 private boolean assertRecords(List<Record> actual) { 235 if (actual.size() != TEST_RECORDS.size()) { 236 return false; 237 } 238 239 for (int i = 0; i < actual.size(); i++) { 240 if (!assertRecord(actual.get(i), TEST_RECORDS.get(i))) { 241 return false; 242 } 243 } 244 245 return true; 246 } 247 248 private boolean assertSelectedRecord(Record actual, int expectedSelectedRecodeIndex) { 249 return assertRecord(actual, TEST_RECORDS.get(expectedSelectedRecodeIndex)); 250 } 251 252 private boolean assertRecord(Record actual, Record expected) { 253 return actual.get(Field.REGION).equals(expected.get(Field.REGION)) && actual 254 .get(Field.REQUEST_COUNT_PER_SECOND).equals(expected.get(Field.REQUEST_COUNT_PER_SECOND)) 255 && actual.get(Field.LOCALITY).equals(expected.get(Field.LOCALITY)); 256 } 257}