Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add block archiving support #485

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
// SPDX-License-Identifier: Apache-2.0
package com.hedera.block.common.utils;

import java.util.Arrays;

/**
* A utility class that deals with logic related to Mathematics.
*/
public final class MathUtilities {
/**
* This array contains the powers of ten from 10^0 to 10^18 (long).
*/
private static final long[] POSITIVE_POWERS_OF_TEN = {
1L,
10L,
100L,
1_000L,
10_000L,
100_000L,
1_000_000L,
10_000_000L,
100_000_000L,
1_000_000_000L,
10_000_000_000L,
100_000_000_000L,
1_000_000_000_000L,
10_000_000_000_000L,
100_000_000_000_000L,
1_000_000_000_000_000L,
10_000_000_000_000_000L,
100_000_000_000_000_000L,
1_000_000_000_000_000_000L
};

/**
* This method checks if the given number is a power of two.
*
Expand All @@ -29,5 +56,29 @@ public static boolean isEven(final int toCheck) {
return (toCheck & 1) == 0;
}

/**
* This method checks if a given long is a positive power of 10.
* E.G.
* <pre>
* isPowerOf10(1) = true
* isPowerOf10(10) = true
* isPowerOf10(100) = true
* isPowerOf10(1000) = true
* isPowerOf10(11) = false
* isPowerOf10(50) = false
* isPowerOf10(99) = false
* isPowerOf10(101) = false
* </pre>
* @param toCheck the long to check
* @return {@code true} if the given long is a power of 10 {@code false} otherwise
*/
public static boolean isPositivePowerOf10(final long toCheck) {
if (toCheck <= 0) {
return false;
} else {
return Arrays.binarySearch(POSITIVE_POWERS_OF_TEN, toCheck) >= 0;
}
}

private MathUtilities() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public final class Preconditions {
private static final String DEFAULT_REQUIRE_POWER_OF_TWO_MESSAGE =
"The input number [%d] is required to be a power of two.";
private static final String DEFAULT_REQUIRE_IS_EVEN = "The input number [%d] is required to be even.";
private static final String DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE =
"The input number [%d] is required to be a positive power of 10.";

/**
* This method asserts a given {@link String} is not blank.
Expand Down Expand Up @@ -294,5 +296,37 @@ public static int requireEven(final int toCheck) {
return requireEven(toCheck, DEFAULT_REQUIRE_IS_EVEN);
}

/**
* This method asserts a given number is a positive power of 10.
*
* @param toCheck the number to check if it is a positive power of 10
* @return the number to check if it is a positive power of 10
* @throws IllegalArgumentException if the input number to check is not a
* positive power of 10
*/
public static int requirePositivePowerOf10(final int toCheck) {
return requirePositivePowerOf10(toCheck, DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE);
}

/**
* This method asserts a given number is a positive power of 10.
*
* @param toCheck the number to check if it is a positive power of 10
* @param errorMessage a formatted string with one decimal parameter for
* {@code toCheck}, must not be {@code null}.<br/>
* Example error message: {@value #DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE}
* @return the number to check if it is a positive power of 10
* @throws IllegalArgumentException if the input number to check is not a
* positive power of 10
* @see java.util.Formatter for more information on error message formatting
*/
public static int requirePositivePowerOf10(final int toCheck, @NonNull final String errorMessage) {
if (!MathUtilities.isPositivePowerOf10(toCheck)) {
throw new IllegalArgumentException(errorMessage.formatted(toCheck));
} else {
return toCheck;
}
}

private Preconditions() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,89 @@ public static Stream<Arguments> zeroAndNegativeIntegers() {
return Stream.concat(Stream.of(Arguments.of(0)), negativeIntegers());
}

public static Stream<Arguments> positivePowersOf10() {
return Stream.of(
Arguments.of(1L),
Arguments.of(10L),
Arguments.of(100L),
Arguments.of(1_000L),
Arguments.of(10_000L),
Arguments.of(100_000L),
Arguments.of(1_000_000L),
Arguments.of(10_000_000L),
Arguments.of(100_000_000L),
Arguments.of(1_000_000_000L),
Arguments.of(10_000_000_000L),
Arguments.of(100_000_000_000L),
Arguments.of(1_000_000_000_000L),
Arguments.of(10_000_000_000_000L),
Arguments.of(100_000_000_000_000L),
Arguments.of(1_000_000_000_000_000L),
Arguments.of(10_000_000_000_000_000L),
Arguments.of(100_000_000_000_000_000L),
Arguments.of(1_000_000_000_000_000_000L));
}

public static Stream<Arguments> negativePowersOf10() {
return Stream.of(
Arguments.of(-1L),
Arguments.of(-10L),
Arguments.of(-100L),
Arguments.of(-1_000L),
Arguments.of(-10_000L),
Arguments.of(-100_000L),
Arguments.of(-1_000_000L),
Arguments.of(-10_000_000L),
Arguments.of(-100_000_000L),
Arguments.of(-1_000_000_000L),
Arguments.of(-10_000_000_000L),
Arguments.of(-100_000_000_000L),
Arguments.of(-1_000_000_000_000L),
Arguments.of(-10_000_000_000_000L),
Arguments.of(-100_000_000_000_000L),
Arguments.of(-1_000_000_000_000_000L),
Arguments.of(-10_000_000_000_000_000L),
Arguments.of(-100_000_000_000_000_000L),
Arguments.of(-1_000_000_000_000_000_000L));
}

public static Stream<Arguments> positiveIntPowersOf10() {
return Stream.of(
Arguments.of(1),
Arguments.of(10),
Arguments.of(100),
Arguments.of(1_000),
Arguments.of(10_000),
Arguments.of(100_000),
Arguments.of(1_000_000),
Arguments.of(10_000_000),
Arguments.of(100_000_000),
Arguments.of(1_000_000_000));
}

public static Stream<Arguments> negativeIntPowersOf10() {
return Stream.of(
Arguments.of(-1),
Arguments.of(-10),
Arguments.of(-100),
Arguments.of(-1_000),
Arguments.of(-10_000),
Arguments.of(-100_000),
Arguments.of(-1_000_000),
Arguments.of(-10_000_000),
Arguments.of(-100_000_000),
Arguments.of(-1_000_000_000));
}

public static Stream<Arguments> nonPowersOf10() {
return Stream.of(
Arguments.of(2),
Arguments.of(11),
Arguments.of(20),
Arguments.of(50),
Arguments.of(101),
Arguments.of(10_100));
}

private CommonsTestUtility() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,31 @@ void testIsEvenFail(final int toTest) {
final boolean actual = MathUtilities.isEven(toTest);
assertThat(actual).isFalse();
}

/**
* This test aims to verify that the
* {@link MathUtilities#isPositivePowerOf10(long)} returns {@code true} if
* the input to check is a positive power of 10.
*/
@ParameterizedTest
@MethodSource("com.hedera.block.common.CommonsTestUtility#positivePowersOf10")
void testIsPositivePowerOf10Pass(final long toTest) {
final boolean actual = MathUtilities.isPositivePowerOf10(toTest);
assertThat(actual).isTrue();
}

/**
* This test aims to verify that the
* {@link MathUtilities#isPositivePowerOf10(long)} returns {@code true} if
* the input to check is a positive power of 10.
*/
@ParameterizedTest
@MethodSource({
"com.hedera.block.common.CommonsTestUtility#negativePowersOf10",
"com.hedera.block.common.CommonsTestUtility#nonPowersOf10"
})
void testIsPositivePowerOf10Fail(final long toTest) {
final boolean actual = MathUtilities.isPositivePowerOf10(toTest);
assertThat(actual).isFalse();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class PreconditionsTest {
private static final String DEFAULT_REQUIRE_POWER_OF_TWO_MESSAGE =
"The input number [%d] is required to be a power of two.";
private static final String DEFAULT_REQUIRE_IS_EVEN = "The input number [%d] is required to be even.";
private static final String DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE =
"The input number [%d] is required to be a positive power of 10.";

/**
* This test aims to verify that the
Expand Down Expand Up @@ -365,6 +367,52 @@ void testRequireEvenFail(final int toTest) {
.withMessage(expectedTestMessage);
}

/**
* This test aims to verify that the
* {@link Preconditions#requirePositivePowerOf10(int)} will return the input
* 'toTest' parameter if the positive power of 10 check passes. Test
* includes overloads.
*
* @param toTest parameterized, the number to test
*/
@ParameterizedTest
@MethodSource("com.hedera.block.common.CommonsTestUtility#positiveIntPowersOf10")
void testRequirePositivePowerOf10Pass(final int toTest) {
final Consumer<Integer> asserts =
actual -> assertThat(actual).isPositive().isEqualTo(toTest);

final int actual = Preconditions.requirePositivePowerOf10(toTest);
assertThat(actual).satisfies(asserts);

final int actualOverload = Preconditions.requirePositivePowerOf10(toTest, "test error message");
assertThat(actualOverload).satisfies(asserts);
}

/**
* This test aims to verify that the
* {@link Preconditions#requirePositivePowerOf10(int)} will throw an
* {@link IllegalArgumentException} if the positive power of 10 check fails.
* Test includes overloads.
*
* @param toTest parameterized, the number to test
*/
@ParameterizedTest
@MethodSource({
"com.hedera.block.common.CommonsTestUtility#negativeIntPowersOf10",
"com.hedera.block.common.CommonsTestUtility#nonPowersOf10"
})
void testRequirePositivePowerOf10Fail(final int toTest) {
assertThatIllegalArgumentException()
.isThrownBy(() -> Preconditions.requirePositivePowerOf10(toTest))
.withMessage(DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE.formatted(toTest));

final String testMessage = DEFAULT_REQUIRE_POSITIVE_POWER_OF_10_MESSAGE.concat(" custom test error message");
final String expectedTestMessage = testMessage.formatted(toTest);
assertThatIllegalArgumentException()
.isThrownBy(() -> Preconditions.requirePositivePowerOf10(toTest, testMessage))
.withMessage(expectedTestMessage);
}

private static Stream<Arguments> validRequireInRangeValues() {
return Stream.of(
Arguments.of(0, 0, 0),
Expand Down
Loading
Loading