blob: 0d3f9c32f0336b3f6bfe84de709b62ac7157684c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.statistics;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import java.util.function.DoubleSupplier;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import org.junit.Before;
import org.junit.Test;
import org.apache.geode.StatisticsType;
import org.apache.geode.internal.statistics.StatisticsImpl.StatisticsLogger;
/**
* Unit tests for {@link StatisticsImpl}.
*/
public class StatisticsImplTest {
// arbitrary values for constructing a StatisticsImpl
private static final String ANY_TEXT_ID = null;
private static final long ANY_NUMERIC_ID = 0;
private static final long ANY_UNIQUE_ID = 0;
private static final int ANY_OS_STAT_FLAGS = 0;
private StatisticsManager statisticsManager;
private StatisticsTypeImpl statisticsType;
private StatisticsImpl statistics;
@Before
public void createStats() {
statisticsManager = mock(StatisticsManager.class);
statisticsType = mock(StatisticsTypeImpl.class);
when(statisticsType.isValidLongId(anyInt())).thenReturn(true);
when(statisticsType.isValidDoubleId(anyInt())).thenReturn(true);
statistics = new SimpleStatistics(statisticsType, ANY_TEXT_ID, ANY_NUMERIC_ID, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
}
@Test
public void invokeIntSuppliersShouldUpdateStats() {
IntSupplier intSupplier = mock(IntSupplier.class);
when(intSupplier.getAsInt()).thenReturn(23);
statistics.setIntSupplier(4, intSupplier);
assertThat(statistics.updateSuppliedValues()).isEqualTo(0);
verify(intSupplier).getAsInt();
assertThat(statistics.getInt(4)).isEqualTo(23);
}
@Test
public void invokeLongSuppliersShouldUpdateStats() {
LongSupplier longSupplier = mock(LongSupplier.class);
when(longSupplier.getAsLong()).thenReturn(23L);
statistics.setLongSupplier(4, longSupplier);
assertThat(statistics.updateSuppliedValues()).isEqualTo(0);
verify(longSupplier).getAsLong();
assertThat(statistics.getLong(4)).isEqualTo(23L);
}
@Test
public void invokeDoubleSuppliersShouldUpdateStats() {
DoubleSupplier doubleSupplier = mock(DoubleSupplier.class);
when(doubleSupplier.getAsDouble()).thenReturn(23.3);
statistics.setDoubleSupplier(4, doubleSupplier);
assertThat(statistics.updateSuppliedValues()).isEqualTo(0);
verify(doubleSupplier).getAsDouble();
assertThat(statistics.getDouble(4)).isEqualTo(23.3);
}
@Test
public void getSupplierCountShouldReturnCorrectCount() {
IntSupplier intSupplier = mock(IntSupplier.class);
statistics.setIntSupplier(4, intSupplier);
assertThat(statistics.getSupplierCount()).isEqualTo(1);
}
@Test
public void invokeSuppliersShouldCatchSupplierErrorsAndReturnCount() {
IntSupplier throwingSupplier = mock(IntSupplier.class);
when(throwingSupplier.getAsInt()).thenThrow(NullPointerException.class);
statistics.setIntSupplier(4, throwingSupplier);
assertThat(statistics.updateSuppliedValues()).isEqualTo(1);
verify(throwingSupplier).getAsInt();
}
@Test
public void invokeSuppliersShouldLogErrorOnlyOnce() {
StatisticsLogger statisticsLogger = mock(StatisticsLogger.class);
statistics = new SimpleStatistics(statisticsType, ANY_TEXT_ID, ANY_NUMERIC_ID, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager, statisticsLogger);
IntSupplier throwingSupplier = mock(IntSupplier.class);
when(throwingSupplier.getAsInt()).thenThrow(NullPointerException.class);
statistics.setIntSupplier(4, throwingSupplier);
assertThat(statistics.updateSuppliedValues()).isEqualTo(1);
// String message, Object p0, Object p1, Object p2
verify(statisticsLogger).logWarning(anyString(), isNull(), anyInt(),
isA(NullPointerException.class));
assertThat(statistics.updateSuppliedValues()).isEqualTo(1);
// Make sure the logger isn't invoked again
verify(statisticsLogger).logWarning(anyString(), isNull(), anyInt(),
isA(NullPointerException.class));
}
@Test
public void badSupplierParamShouldThrowError() {
IntSupplier intSupplier = mock(IntSupplier.class);
when(intSupplier.getAsInt()).thenReturn(23);
when(statisticsType.isValidLongId(anyInt())).thenReturn(false);
Throwable thrown = catchThrowable(() -> statistics.setIntSupplier(23, intSupplier));
assertThat(thrown).isInstanceOf(IllegalArgumentException.class);
}
@Test
public void nonEmptyTextId_usesGivenTextId() {
String nonEmptyTextId = "non-empty-text-id";
statistics = new SimpleStatistics(statisticsType, nonEmptyTextId, ANY_NUMERIC_ID, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getTextId()).isEqualTo(nonEmptyTextId);
}
@Test
public void nullTextId_usesNameFromStatisticsManager() {
String nameFromStatisticsManager = "statistics-manager-name";
when(statisticsManager.getName()).thenReturn(nameFromStatisticsManager);
String nullTextId = null;
statistics = new SimpleStatistics(statisticsType, nullTextId, ANY_NUMERIC_ID, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getTextId()).isEqualTo(nameFromStatisticsManager);
}
@Test
public void emptyTextId_usesNameFromStatisticsManager() {
String nameFromStatisticsManager = "statistics-manager-name";
when(statisticsManager.getName()).thenReturn(nameFromStatisticsManager);
String emptyTextId = "";
statistics = new SimpleStatistics(statisticsType, emptyTextId, ANY_NUMERIC_ID, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getTextId()).isEqualTo(nameFromStatisticsManager);
}
@Test
public void positiveNumericId_usesGivenNumericId() {
int positiveNumericId = 21;
statistics = new SimpleStatistics(statisticsType, ANY_TEXT_ID, positiveNumericId, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getNumericId()).isEqualTo(positiveNumericId);
}
@Test
public void negativeNumericId_usesGivenNumericId() {
int negativeNumericId = -21;
statistics = new SimpleStatistics(statisticsType, ANY_TEXT_ID, negativeNumericId, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getNumericId()).isEqualTo(negativeNumericId);
}
@Test
public void zeroNumericId_usesPidFromStatisticsManager() {
int pidFromStatisticsManager = 42;
when(statisticsManager.getPid()).thenReturn(pidFromStatisticsManager);
int zeroNumericId = 0;
statistics = new SimpleStatistics(statisticsType, ANY_TEXT_ID, zeroNumericId, ANY_UNIQUE_ID,
ANY_OS_STAT_FLAGS, statisticsManager);
assertThat(statistics.getNumericId()).isEqualTo(pidFromStatisticsManager);
}
private static class SimpleStatistics extends StatisticsImpl {
private final Map<Number, Number> values = new HashMap<>();
SimpleStatistics(StatisticsType type, String textId, long numericId, long uniqueId,
int osStatFlags, StatisticsManager statisticsManager) {
super(type, textId, numericId, uniqueId, osStatFlags, statisticsManager);
}
SimpleStatistics(StatisticsType type, String textId, long numericId, long uniqueId,
int osStatFlags, StatisticsManager statisticsManager, StatisticsLogger statisticsLogger) {
super(type, textId, numericId, uniqueId, osStatFlags, statisticsManager, statisticsLogger);
}
@Override
public boolean isAtomic() {
return false;
}
@Override
protected void _setLong(int offset, long value) {
values.put(offset, value);
}
@Override
protected void _setDouble(int offset, double value) {
values.put(offset, value);
}
@Override
protected long _getLong(int offset) {
return (long) values.get(offset);
}
@Override
protected double _getDouble(int offset) {
return (double) values.get(offset);
}
@Override
protected void _incLong(int offset, long delta) {
values.put(offset, (long) values.get(delta) + 1);
}
@Override
protected void _incDouble(int offset, double delta) {
values.put(offset, (double) values.get(delta) + 1);
}
}
}