Skip to content

Commit

Permalink
add abstract data based test for migrated endpoints (#5415)
Browse files Browse the repository at this point in the history
Currently supports `ChainDataProvider`.

Signed-off-by: Paul Harris <[email protected]>
  • Loading branch information
rolfyone authored May 4, 2022
1 parent 7f0053d commit 8f80286
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 46 deletions.
1 change: 1 addition & 0 deletions data/beaconrestapi/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
testImplementation testFixtures(project(':infrastructure:time'))

testImplementation testFixtures(project(':infrastructure:json'))
testImplementation testFixtures(project(':ethereum:core'))

testCompileOnly 'io.libp2p:jvm-libp2p-minimal'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

public abstract class AbstractMigratedBeaconHandlerTest {
protected final Eth2P2PNetwork eth2P2PNetwork = mock(Eth2P2PNetwork.class);
protected final Spec spec = TestSpecFactory.createMinimalPhase0();
protected Spec spec = TestSpecFactory.createMinimalPhase0();

protected final Context context = mock(Context.class);
protected final JsonProvider jsonProvider = new JsonProvider();
Expand All @@ -69,7 +69,7 @@ public abstract class AbstractMigratedBeaconHandlerTest {

private final ArgumentCaptor<byte[]> args = ArgumentCaptor.forClass(byte[].class);

protected final ChainDataProvider chainDataProvider = mock(ChainDataProvider.class);
protected ChainDataProvider chainDataProvider = mock(ChainDataProvider.class);
protected final ValidatorDataProvider validatorDataProvider = mock(ValidatorDataProvider.class);

protected SyncingStatus getSyncStatus(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2022 ConsenSys AG.
*
* Licensed 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 tech.pegasys.teku.beaconrestapi;

import tech.pegasys.teku.api.ChainDataProvider;
import tech.pegasys.teku.core.ChainBuilder;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.TestSpecFactory;
import tech.pegasys.teku.statetransition.validatorcache.ActiveValidatorCache;
import tech.pegasys.teku.statetransition.validatorcache.ActiveValidatorChannel;
import tech.pegasys.teku.storage.client.ChainUpdater;
import tech.pegasys.teku.storage.client.CombinedChainDataClient;
import tech.pegasys.teku.storage.client.RecentChainData;
import tech.pegasys.teku.storage.server.StateStorageMode;
import tech.pegasys.teku.storage.storageSystem.InMemoryStorageSystemBuilder;
import tech.pegasys.teku.storage.storageSystem.StorageSystem;

public class AbstractMigratedBeaconHandlerWithChainDataProviderTest
extends AbstractMigratedBeaconHandlerTest {
protected ChainBuilder chainBuilder;
protected ChainUpdater chainUpdater;

protected ActiveValidatorChannel activeValidatorChannel;
protected StorageSystem storageSystem =
InMemoryStorageSystemBuilder.buildDefault(StateStorageMode.ARCHIVE);
protected CombinedChainDataClient combinedChainDataClient;
protected RecentChainData recentChainData = storageSystem.recentChainData();

public void initialise(final SpecMilestone specMilestone) {
setupStorage(StateStorageMode.ARCHIVE, specMilestone, false);
}

public void genesis() {
storageSystem.chainUpdater().initializeGenesis();
}

private void setupStorage(
final StateStorageMode storageMode,
final SpecMilestone specMilestone,
final boolean storeNonCanonicalBlocks) {
this.spec = TestSpecFactory.createMinimal(specMilestone);
this.storageSystem =
InMemoryStorageSystemBuilder.create()
.specProvider(spec)
.storageMode(storageMode)
.storeNonCanonicalBlocks(storeNonCanonicalBlocks)
.build();
activeValidatorChannel = new ActiveValidatorCache(spec, 10);
recentChainData = storageSystem.recentChainData();
combinedChainDataClient = storageSystem.combinedChainDataClient();

chainBuilder = storageSystem.chainBuilder();
chainUpdater = storageSystem.chainUpdater();
chainDataProvider = new ChainDataProvider(spec, recentChainData, combinedChainDataClient);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.when;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_BAD_REQUEST;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_INTERNAL_SERVER_ERROR;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_OK;
Expand All @@ -24,21 +23,21 @@
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerWithChainDataProviderTest;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.infrastructure.restapi.StubRestApiRequest;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.genesis.GenesisData;

public class GetGenesisTest extends AbstractMigratedBeaconHandlerTest {
public class GetGenesisTest extends AbstractMigratedBeaconHandlerWithChainDataProviderTest {
private StubRestApiRequest request;
final GetGenesis handler = new GetGenesis(chainDataProvider);
final UInt64 genesisTime = dataStructureUtil.randomUInt64();
final Bytes32 genesisValidatorsRoot = dataStructureUtil.randomBytes32();
final Bytes4 fork = dataStructureUtil.randomBytes4();
final GetGenesis.ResponseData responseData =
new GetGenesis.ResponseData(new GenesisData(genesisTime, genesisValidatorsRoot), fork);
final GenesisData expectedGenesisData = new GenesisData(genesisTime, genesisValidatorsRoot);

@BeforeEach
void setup() {
Expand All @@ -47,23 +46,27 @@ void setup() {

@Test
public void shouldReturnUnavailableWhenStoreNotAvailable() throws Exception {
when(chainDataProvider.isStoreAvailable()).thenReturn(false);

handler.handleRequest(request);
assertThat(request.getResponseCode()).isEqualTo(SC_NOT_FOUND);
}

@Test
public void shouldReturnGenesisInformation() throws Exception {
when(chainDataProvider.isStoreAvailable()).thenReturn(true);
when(chainDataProvider.getGenesisStateData()).thenReturn(expectedGenesisData);
initialise(SpecMilestone.PHASE0);
genesis();
final GetGenesis handler = new GetGenesis(chainDataProvider);

final GenesisData genesisData = chainDataProvider.getGenesisStateData();

final GetGenesis.ResponseData expectedData =
new GetGenesis.ResponseData(
genesisData.getGenesisTime(),
genesisData.getGenesisValidatorsRoot(),
chainDataProvider.getGenesisForkVersion());

handler.handleRequest(request);
assertThat(request.getResponseCode()).isEqualTo(SC_OK);
assertThat(request.getResponseBody())
.isEqualTo(
new GetGenesis.ResponseData(
genesisTime, genesisValidatorsRoot, chainDataProvider.getGenesisForkVersion()));
assertThat(request.getResponseBody()).isEqualTo(expectedData);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,33 @@

package tech.pegasys.teku.beaconrestapi.handlers.v1.beacon;

import static org.mockito.ArgumentMatchers.eq;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.when;

import java.util.Map;
import java.util.Optional;
import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerWithChainDataProviderTest;
import tech.pegasys.teku.infrastructure.restapi.endpoints.JavalinRestApiRequest;
import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiRequest;
import tech.pegasys.teku.spec.datastructures.metadata.StateAndMetaData;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;

public class GetStateFinalityCheckpointsTest extends AbstractMigratedBeaconHandlerTest {
public class GetStateFinalityCheckpointsTest
extends AbstractMigratedBeaconHandlerWithChainDataProviderTest {

@Test
public void shouldReturnFinalityCheckpointsInfo() throws Exception {
initialise(SpecMilestone.PHASE0);
genesis();

chainUpdater.updateBestBlock(chainBuilder.generateNextBlock());
chainUpdater.finalizeCurrentChain();

final GetStateFinalityCheckpoints handler = new GetStateFinalityCheckpoints(chainDataProvider);
final BeaconState beaconState = dataStructureUtil.randomBeaconState();
final StateAndMetaData stateAndMetaData =
new StateAndMetaData(beaconState, spec.getGenesisSpec().getMilestone(), false, false, true);
when(chainDataProvider.getBeaconStateAndMetadata(eq("head")))
.thenReturn(SafeFuture.completedFuture(Optional.of(stateAndMetaData)));
final BeaconState beaconState = recentChainData.getBestState().orElseThrow().get();

when(context.pathParamMap()).thenReturn(Map.of("state_id", "head"));
RestApiRequest request = new JavalinRestApiRequest(context, handler.getMetadata());
final RestApiRequest request = new JavalinRestApiRequest(context, handler.getMetadata());

handler.handleRequest(request);

Expand All @@ -53,6 +54,6 @@ public void shouldReturnFinalityCheckpointsInfo() throws Exception {
beaconState.getFinalizedCheckpoint().getEpoch(),
beaconState.getFinalizedCheckpoint().getRoot());

AssertionsForClassTypes.assertThat(getFutureResultString()).isEqualTo(expected);
assertThat(getFutureResultString()).isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,40 @@
package tech.pegasys.teku.beaconrestapi.handlers.v1.beacon;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Map;
import java.util.Optional;
import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerWithChainDataProviderTest;
import tech.pegasys.teku.infrastructure.restapi.endpoints.JavalinRestApiRequest;
import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiRequest;
import tech.pegasys.teku.spec.datastructures.metadata.StateAndMetaData;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;

public class GetStateRootTest extends AbstractMigratedBeaconHandlerTest {
public class GetStateRootTest extends AbstractMigratedBeaconHandlerWithChainDataProviderTest {

@BeforeEach
public void setup() {
initialise(SpecMilestone.PHASE0);
genesis();
}

@Test
public void shouldReturnRootInfo() throws Exception {
final BeaconState state = recentChainData.getBestState().orElseThrow().get();
final GetStateRoot handler = new GetStateRoot(chainDataProvider);
final StateAndMetaData stateAndMetaData =
new StateAndMetaData(
dataStructureUtil.randomBeaconState(),
spec.getGenesisSpec().getMilestone(),
false,
false,
true);
when(chainDataProvider.getBeaconStateAndMetadata(eq("head")))
.thenReturn(SafeFuture.completedFuture(Optional.of(stateAndMetaData)));

when(context.pathParamMap()).thenReturn(Map.of("state_id", "head"));
RestApiRequest request = new JavalinRestApiRequest(context, handler.getMetadata());

handler.handleRequest(request);

String expected =
String.format(
"{\"data\":{\"root\":\"%s\"}}",
stateAndMetaData.getData().hashTreeRoot().toHexString());
String.format("{\"data\":{\"root\":\"%s\"}}", state.hashTreeRoot().toHexString());
AssertionsForClassTypes.assertThat(getFutureResultString()).isEqualTo(expected);
verify(context, never()).status(any());
}
Expand Down

0 comments on commit 8f80286

Please sign in to comment.