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