use of org.hyperledger.fabric.sdk.BlockEvent in project fabric-sdk-java by hyperledger.
the class End2endIT method runChannel.
// CHECKSTYLE.OFF: Method length is 320 lines (max allowed is 150).
void runChannel(HFClient client, Channel channel, boolean installChaincode, SampleOrg sampleOrg, int delta) {
class ChaincodeEventCapture {
final String handle;
final BlockEvent blockEvent;
final ChaincodeEvent chaincodeEvent;
ChaincodeEventCapture(String handle, BlockEvent blockEvent, ChaincodeEvent chaincodeEvent) {
this.handle = handle;
this.blockEvent = blockEvent;
this.chaincodeEvent = chaincodeEvent;
}
}
// Test list to capture chaincode events.
Vector<ChaincodeEventCapture> chaincodeEvents = new Vector<>();
try {
final String channelName = channel.getName();
boolean isFooChain = FOO_CHANNEL_NAME.equals(channelName);
out("Running channel %s", channelName);
Collection<Orderer> orderers = channel.getOrderers();
final ChaincodeID chaincodeID;
Collection<ProposalResponse> responses;
Collection<ProposalResponse> successful = new LinkedList<>();
Collection<ProposalResponse> failed = new LinkedList<>();
// Register a chaincode event listener that will trigger for any chaincode id and only for EXPECTED_EVENT_NAME event.
String chaincodeEventListenerHandle = channel.registerChaincodeEventListener(Pattern.compile(".*"), Pattern.compile(Pattern.quote(EXPECTED_EVENT_NAME)), (handle, blockEvent, chaincodeEvent) -> {
chaincodeEvents.add(new ChaincodeEventCapture(handle, blockEvent, chaincodeEvent));
String es = blockEvent.getPeer() != null ? blockEvent.getPeer().getName() : blockEvent.getEventHub().getName();
out("RECEIVED Chaincode event with handle: %s, chaincode Id: %s, chaincode event name: %s, " + "transaction id: %s, event payload: \"%s\", from eventhub: %s", handle, chaincodeEvent.getChaincodeId(), chaincodeEvent.getEventName(), chaincodeEvent.getTxId(), new String(chaincodeEvent.getPayload()), es);
});
// For non foo channel unregister event listener to test events are not called.
if (!isFooChain) {
channel.unregisterChaincodeEventListener(chaincodeEventListenerHandle);
chaincodeEventListenerHandle = null;
}
ChaincodeID.Builder chaincodeIDBuilder = ChaincodeID.newBuilder().setName(CHAIN_CODE_NAME).setVersion(CHAIN_CODE_VERSION);
if (null != CHAIN_CODE_PATH) {
chaincodeIDBuilder.setPath(CHAIN_CODE_PATH);
}
chaincodeID = chaincodeIDBuilder.build();
if (installChaincode) {
// //////////////////////////
// Install Proposal Request
//
client.setUserContext(sampleOrg.getPeerAdmin());
out("Creating install proposal");
InstallProposalRequest installProposalRequest = client.newInstallProposalRequest();
installProposalRequest.setChaincodeID(chaincodeID);
if (isFooChain) {
// on foo chain install from directory.
// //For GO language and serving just a single user, chaincodeSource is mostly likely the users GOPATH
installProposalRequest.setChaincodeSourceLocation(Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH).toFile());
} else {
if (CHAIN_CODE_LANG.equals(Type.GO_LANG)) {
installProposalRequest.setChaincodeInputStream(Util.generateTarGzInputStream((Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH, "src", CHAIN_CODE_PATH).toFile()), Paths.get("src", CHAIN_CODE_PATH).toString()));
} else {
installProposalRequest.setChaincodeInputStream(Util.generateTarGzInputStream((Paths.get(TEST_FIXTURES_PATH, CHAIN_CODE_FILEPATH).toFile()), "src"));
}
}
installProposalRequest.setChaincodeVersion(CHAIN_CODE_VERSION);
installProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
out("Sending install proposal");
// //////////////////////////
// only a client from the same org as the peer can issue an install request
int numInstallProposal = 0;
// Set<String> orgs = orgPeers.keySet();
// for (SampleOrg org : testSampleOrgs) {
Collection<Peer> peers = channel.getPeers();
numInstallProposal = numInstallProposal + peers.size();
responses = client.sendInstallProposal(installProposalRequest, peers);
for (ProposalResponse response : responses) {
if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
out("Successful install proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName());
successful.add(response);
} else {
failed.add(response);
}
}
// }
out("Received %d install proposal responses. Successful+verified: %d . Failed: %d", numInstallProposal, successful.size(), failed.size());
if (failed.size() > 0) {
ProposalResponse first = failed.iterator().next();
fail("Not enough endorsers for install :" + successful.size() + ". " + first.getMessage());
}
}
// client.setUserContext(sampleOrg.getUser(TEST_ADMIN_NAME));
// final ChaincodeID chaincodeID = firstInstallProposalResponse.getChaincodeID();
// Note installing chaincode does not require transaction no need to
// send to Orderers
// /////////////
// // Instantiate chaincode.
InstantiateProposalRequest instantiateProposalRequest = client.newInstantiationProposalRequest();
instantiateProposalRequest.setProposalWaitTime(testConfig.getProposalWaitTime());
instantiateProposalRequest.setChaincodeID(chaincodeID);
instantiateProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
instantiateProposalRequest.setFcn("init");
instantiateProposalRequest.setArgs(new String[] { "a", "500", "b", "" + (200 + delta) });
Map<String, byte[]> tm = new HashMap<>();
tm.put("HyperLedgerFabric", "InstantiateProposalRequest:JavaSDK".getBytes(UTF_8));
tm.put("method", "InstantiateProposalRequest".getBytes(UTF_8));
instantiateProposalRequest.setTransientMap(tm);
/*
policy OR(Org1MSP.member, Org2MSP.member) meaning 1 signature from someone in either Org1 or Org2
See README.md Chaincode endorsement policies section for more details.
*/
ChaincodeEndorsementPolicy chaincodeEndorsementPolicy = new ChaincodeEndorsementPolicy();
chaincodeEndorsementPolicy.fromYamlFile(new File(TEST_FIXTURES_PATH + "/sdkintegration/chaincodeendorsementpolicy.yaml"));
instantiateProposalRequest.setChaincodeEndorsementPolicy(chaincodeEndorsementPolicy);
out("Sending instantiateProposalRequest to all peers with arguments: a and b set to 100 and %s respectively", "" + (200 + delta));
successful.clear();
failed.clear();
if (isFooChain) {
// Send responses both ways with specifying peers and by using those on the channel.
responses = channel.sendInstantiationProposal(instantiateProposalRequest, channel.getPeers());
} else {
responses = channel.sendInstantiationProposal(instantiateProposalRequest);
}
for (ProposalResponse response : responses) {
if (response.isVerified() && response.getStatus() == ProposalResponse.Status.SUCCESS) {
successful.add(response);
out("Succesful instantiate proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName());
} else {
failed.add(response);
}
}
out("Received %d instantiate proposal responses. Successful+verified: %d . Failed: %d", responses.size(), successful.size(), failed.size());
if (failed.size() > 0) {
for (ProposalResponse fail : failed) {
out("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + fail.getMessage() + ", on peer" + fail.getPeer());
}
ProposalResponse first = failed.iterator().next();
fail("Not enough endorsers for instantiate :" + successful.size() + "endorser failed with " + first.getMessage() + ". Was verified:" + first.isVerified());
}
// /////////////
// / Send instantiate transaction to orderer
out("Sending instantiateTransaction to orderer with a and b set to 100 and %s respectively", "" + (200 + delta));
// Specify what events should complete the interest in this transaction. This is the default
// for all to complete. It's possible to specify many different combinations like
// any from a group, all from one group and just one from another or even None(NOfEvents.createNoEvents).
// See. Channel.NOfEvents
Channel.NOfEvents nOfEvents = createNofEvents();
if (!channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)).isEmpty()) {
nOfEvents.addPeers(channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)));
}
if (!channel.getEventHubs().isEmpty()) {
nOfEvents.addEventHubs(channel.getEventHubs());
}
channel.sendTransaction(successful, // Basically the default options but shows it's usage.
createTransactionOptions().userContext(// could be a different user context. this is the default.
client.getUserContext()).shuffleOrders(// don't shuffle any orderers the default is true.
false).orderers(// specify the orderers we want to try this transaction. Fails once all Orderers are tried.
channel.getOrderers()).nOfEvents(// The events to signal the completion of the interest in the transaction
nOfEvents)).thenApply(transactionEvent -> {
waitOnFabric(0);
// must be valid to be here.
assertTrue(transactionEvent.isValid());
// musth have a signature.
assertNotNull(transactionEvent.getSignature());
// This is the blockevent that has this transaction.
BlockEvent blockEvent = transactionEvent.getBlockEvent();
// Make sure the RAW Fabric block is returned.
assertNotNull(blockEvent.getBlock());
out("Finished instantiate transaction with transaction id %s", transactionEvent.getTransactionID());
try {
assertEquals(blockEvent.getChannelId(), channel.getName());
successful.clear();
failed.clear();
client.setUserContext(sampleOrg.getUser(TESTUSER_1_NAME));
// /////////////
// / Send transaction proposal to all peers
TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();
transactionProposalRequest.setChaincodeID(chaincodeID);
transactionProposalRequest.setChaincodeLanguage(CHAIN_CODE_LANG);
// transactionProposalRequest.setFcn("invoke");
transactionProposalRequest.setFcn("move");
transactionProposalRequest.setProposalWaitTime(testConfig.getProposalWaitTime());
transactionProposalRequest.setArgs("a", "b", "100");
Map<String, byte[]> tm2 = new HashMap<>();
// Just some extra junk in transient map
tm2.put("HyperLedgerFabric", "TransactionProposalRequest:JavaSDK".getBytes(UTF_8));
// ditto
tm2.put("method", "TransactionProposalRequest".getBytes(UTF_8));
// This should be returned see chaincode why.
tm2.put("result", ":)".getBytes(UTF_8));
// This should trigger an event see chaincode why.
tm2.put(EXPECTED_EVENT_NAME, EXPECTED_EVENT_DATA);
transactionProposalRequest.setTransientMap(tm2);
out("sending transactionProposal to all peers with arguments: move(a,b,100)");
Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposal(transactionProposalRequest, channel.getPeers());
for (ProposalResponse response : transactionPropResp) {
if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
out("Successful transaction proposal response Txid: %s from peer %s", response.getTransactionID(), response.getPeer().getName());
successful.add(response);
} else {
failed.add(response);
}
}
// Check that all the proposals are consistent with each other. We should have only one set
// where all the proposals above are consistent. Note the when sending to Orderer this is done automatically.
// Shown here as an example that applications can invoke and select.
// See org.hyperledger.fabric.sdk.proposal.consistency_validation config property.
Collection<Set<ProposalResponse>> proposalConsistencySets = SDKUtils.getProposalConsistencySets(transactionPropResp);
if (proposalConsistencySets.size() != 1) {
fail(format("Expected only one set of consistent proposal responses but got %d", proposalConsistencySets.size()));
}
out("Received %d transaction proposal responses. Successful+verified: %d . Failed: %d", transactionPropResp.size(), successful.size(), failed.size());
if (failed.size() > 0) {
ProposalResponse firstTransactionProposalResponse = failed.iterator().next();
fail("Not enough endorsers for invoke(move a,b,100):" + failed.size() + " endorser error: " + firstTransactionProposalResponse.getMessage() + ". Was verified: " + firstTransactionProposalResponse.isVerified());
}
out("Successfully received transaction proposal responses.");
ProposalResponse resp = successful.iterator().next();
// This is the data returned by the chaincode.
byte[] x = resp.getChaincodeActionResponsePayload();
String resultAsString = null;
if (x != null) {
resultAsString = new String(x, "UTF-8");
}
assertEquals(":)", resultAsString);
// Chaincode's status.
assertEquals(200, resp.getChaincodeActionResponseStatus());
TxReadWriteSetInfo readWriteSetInfo = resp.getChaincodeActionResponseReadWriteSetInfo();
// See blockwalker below how to transverse this
assertNotNull(readWriteSetInfo);
assertTrue(readWriteSetInfo.getNsRwsetCount() > 0);
ChaincodeID cid = resp.getChaincodeID();
assertNotNull(cid);
final String path = cid.getPath();
if (null == CHAIN_CODE_PATH) {
assertTrue(path == null || "".equals(path));
} else {
assertEquals(CHAIN_CODE_PATH, path);
}
assertEquals(CHAIN_CODE_NAME, cid.getName());
assertEquals(CHAIN_CODE_VERSION, cid.getVersion());
// //////////////////////////
// Send Transaction Transaction to orderer
out("Sending chaincode transaction(move a,b,100) to orderer.");
return channel.sendTransaction(successful).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
} catch (Exception e) {
out("Caught an exception while invoking chaincode");
e.printStackTrace();
fail("Failed invoking chaincode with error : " + e.getMessage());
}
return null;
}).thenApply(transactionEvent -> {
try {
waitOnFabric(0);
// must be valid to be here.
assertTrue(transactionEvent.isValid());
out("Finished transaction with transaction id %s", transactionEvent.getTransactionID());
// used in the channel queries later
testTxID = transactionEvent.getTransactionID();
// //////////////////////////
// Send Query Proposal to all peers
//
String expect = "" + (300 + delta);
out("Now query chaincode for the value of b.");
QueryByChaincodeRequest queryByChaincodeRequest = client.newQueryProposalRequest();
queryByChaincodeRequest.setArgs(new String[] { "b" });
queryByChaincodeRequest.setFcn("query");
queryByChaincodeRequest.setChaincodeID(chaincodeID);
Map<String, byte[]> tm2 = new HashMap<>();
tm2.put("HyperLedgerFabric", "QueryByChaincodeRequest:JavaSDK".getBytes(UTF_8));
tm2.put("method", "QueryByChaincodeRequest".getBytes(UTF_8));
queryByChaincodeRequest.setTransientMap(tm2);
Collection<ProposalResponse> queryProposals = channel.queryByChaincode(queryByChaincodeRequest, channel.getPeers());
for (ProposalResponse proposalResponse : queryProposals) {
if (!proposalResponse.isVerified() || proposalResponse.getStatus() != ProposalResponse.Status.SUCCESS) {
fail("Failed query proposal from peer " + proposalResponse.getPeer().getName() + " status: " + proposalResponse.getStatus() + ". Messages: " + proposalResponse.getMessage() + ". Was verified : " + proposalResponse.isVerified());
} else {
String payload = proposalResponse.getProposalResponse().getResponse().getPayload().toStringUtf8();
out("Query payload of b from peer %s returned %s", proposalResponse.getPeer().getName(), payload);
assertEquals(payload, expect);
}
}
return null;
} catch (Exception e) {
out("Caught exception while running query");
e.printStackTrace();
fail("Failed during chaincode query with error : " + e.getMessage());
}
return null;
}).exceptionally(e -> {
if (e instanceof TransactionEventException) {
BlockEvent.TransactionEvent te = ((TransactionEventException) e).getTransactionEvent();
if (te != null) {
throw new AssertionError(format("Transaction with txid %s failed. %s", te.getTransactionID(), e.getMessage()), e);
}
}
throw new AssertionError(format("Test failed with %s exception %s", e.getClass().getName(), e.getMessage()), e);
}).get(testConfig.getTransactionWaitTime(), TimeUnit.SECONDS);
// Channel queries
// We can only send channel queries to peers that are in the same org as the SDK user context
// Get the peers from the current org being used and pick one randomly to send the queries to.
// Set<Peer> peerSet = sampleOrg.getPeers();
// Peer queryPeer = peerSet.iterator().next();
// out("Using peer %s for channel queries", queryPeer.getName());
BlockchainInfo channelInfo = channel.queryBlockchainInfo();
out("Channel info for : " + channelName);
out("Channel height: " + channelInfo.getHeight());
String chainCurrentHash = Hex.encodeHexString(channelInfo.getCurrentBlockHash());
String chainPreviousHash = Hex.encodeHexString(channelInfo.getPreviousBlockHash());
out("Chain current block hash: " + chainCurrentHash);
out("Chainl previous block hash: " + chainPreviousHash);
// Query by block number. Should return latest block, i.e. block number 2
BlockInfo returnedBlock = channel.queryBlockByNumber(channelInfo.getHeight() - 1);
String previousHash = Hex.encodeHexString(returnedBlock.getPreviousHash());
out("queryBlockByNumber returned correct block with blockNumber " + returnedBlock.getBlockNumber() + " \n previous_hash " + previousHash);
assertEquals(channelInfo.getHeight() - 1, returnedBlock.getBlockNumber());
assertEquals(chainPreviousHash, previousHash);
// Query by block hash. Using latest block's previous hash so should return block number 1
byte[] hashQuery = returnedBlock.getPreviousHash();
returnedBlock = channel.queryBlockByHash(hashQuery);
out("queryBlockByHash returned block with blockNumber " + returnedBlock.getBlockNumber());
assertEquals(channelInfo.getHeight() - 2, returnedBlock.getBlockNumber());
// Query block by TxID. Since it's the last TxID, should be block 2
returnedBlock = channel.queryBlockByTransactionID(testTxID);
out("queryBlockByTxID returned block with blockNumber " + returnedBlock.getBlockNumber());
assertEquals(channelInfo.getHeight() - 1, returnedBlock.getBlockNumber());
// query transaction by ID
TransactionInfo txInfo = channel.queryTransactionByID(testTxID);
out("QueryTransactionByID returned TransactionInfo: txID " + txInfo.getTransactionID() + "\n validation code " + txInfo.getValidationCode().getNumber());
if (chaincodeEventListenerHandle != null) {
channel.unregisterChaincodeEventListener(chaincodeEventListenerHandle);
// Should be two. One event in chaincode and two notification for each of the two event hubs
final int numberEventsExpected = channel.getEventHubs().size() + channel.getPeers(EnumSet.of(PeerRole.EVENT_SOURCE)).size();
// just make sure we get the notifications.
for (int i = 15; i > 0; --i) {
if (chaincodeEvents.size() == numberEventsExpected) {
break;
} else {
// wait for the events.
Thread.sleep(90);
}
}
assertEquals(numberEventsExpected, chaincodeEvents.size());
for (ChaincodeEventCapture chaincodeEventCapture : chaincodeEvents) {
assertEquals(chaincodeEventListenerHandle, chaincodeEventCapture.handle);
assertEquals(testTxID, chaincodeEventCapture.chaincodeEvent.getTxId());
assertEquals(EXPECTED_EVENT_NAME, chaincodeEventCapture.chaincodeEvent.getEventName());
assertTrue(Arrays.equals(EXPECTED_EVENT_DATA, chaincodeEventCapture.chaincodeEvent.getPayload()));
assertEquals(CHAIN_CODE_NAME, chaincodeEventCapture.chaincodeEvent.getChaincodeId());
BlockEvent blockEvent = chaincodeEventCapture.blockEvent;
assertEquals(channelName, blockEvent.getChannelId());
// assertTrue(channel.getEventHubs().contains(blockEvent.getEventHub()));
}
} else {
assertTrue(chaincodeEvents.isEmpty());
}
out("Running for Channel %s done", channelName);
} catch (Exception e) {
out("Caught an exception running channel %s", channel.getName());
e.printStackTrace();
fail("Test failed with error : " + e.getMessage());
}
}
use of org.hyperledger.fabric.sdk.BlockEvent in project fabric-sdk-java by hyperledger.
the class End2endAndBackAgainIT method testPeerServiceEventingReplay.
/**
* This code test the replay feature of the new peer event services.
* Instead of the default of starting the eventing peer to retrieve the newest block it sets it
* retrieve starting from the start parameter. Also checks with block and filterblock replays.
* Depends on end2end and end2endAndBackagain of have fully run to have the blocks need to work with.
*
* @param client
* @param replayTestChannel
* @param start
* @param stop
* @param useFilteredBlocks
* @throws InvalidArgumentException
*/
private void testPeerServiceEventingReplay(HFClient client, Channel replayTestChannel, final long start, final long stop, final boolean useFilteredBlocks) throws InvalidArgumentException {
if (testConfig.isRunningAgainstFabric10()) {
// not supported for v1.0
return;
}
// not yet initialized
assertFalse(replayTestChannel.isInitialized());
// not yet shutdown.
assertFalse(replayTestChannel.isShutdown());
// Remove all peers just have one ledger peer and one eventing peer.
List<Peer> savedPeers = new ArrayList<>(replayTestChannel.getPeers());
for (Peer peer : savedPeers) {
replayTestChannel.removePeer(peer);
}
// need at least two
assertTrue(savedPeers.size() > 1);
final Peer eventingPeer = savedPeers.remove(0);
Peer ledgerPeer = savedPeers.remove(0);
// no more peers.
assertTrue(replayTestChannel.getPeers().isEmpty());
// just checking :)
assertTrue(replayTestChannel.getPeers(EnumSet.of(PeerRole.CHAINCODE_QUERY, PeerRole.ENDORSING_PEER)).isEmpty());
// just checking
assertTrue(replayTestChannel.getPeers(EnumSet.of(PeerRole.LEDGER_QUERY)).isEmpty());
// should be known by client.
assertNotNull(client.getChannel(replayTestChannel.getName()));
final PeerOptions eventingPeerOptions = createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.EVENT_SOURCE));
if (useFilteredBlocks) {
eventingPeerOptions.registerEventsForFilteredBlocks();
}
if (-1L == stop) {
// the height of the blockchain
// Eventing peer start getting blocks from block 0
replayTestChannel.addPeer(eventingPeer, eventingPeerOptions.startEvents(start));
} else {
replayTestChannel.addPeer(eventingPeer, eventingPeerOptions.startEvents(start).stopEvents(// Eventing peer start getting blocks from block 0
stop));
}
// add a ledger peer
replayTestChannel.addPeer(ledgerPeer, createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.LEDGER_QUERY)));
// future to set when done.
CompletableFuture<Long> done = new CompletableFuture<>();
// some variable used by the block listener being set up.
final AtomicLong bcount = new AtomicLong(0);
final AtomicLong stopValue = new AtomicLong(stop == -1L ? Long.MAX_VALUE : stop);
final Channel finalChannel = replayTestChannel;
final Map<Long, BlockEvent> blockEvents = Collections.synchronizedMap(new HashMap<>(100));
final String blockListenerHandle = replayTestChannel.registerBlockListener(blockEvent -> {
try {
final long blockNumber = blockEvent.getBlockNumber();
BlockEvent seen = blockEvents.put(blockNumber, blockEvent);
assertNull(format("Block number %d seen twice", blockNumber), seen);
assertTrue(format("Wrong type of block seen block number %d. expected filtered block %b but got %b", blockNumber, useFilteredBlocks, blockEvent.isFiltered()), useFilteredBlocks ? blockEvent.isFiltered() : !blockEvent.isFiltered());
// count starts with 0 not 1 !
final long count = bcount.getAndIncrement();
if (count == 0 && stop == -1L) {
final BlockchainInfo blockchainInfo = finalChannel.queryBlockchainInfo();
long lh = blockchainInfo.getHeight();
// blocks 0L 9L are on chain height 10 .. stop on 9
stopValue.set(lh - 1L);
// out("height: %d", lh);
if (bcount.get() + start > stopValue.longValue()) {
// test with latest count.
// report back latest count.
done.complete(bcount.get());
}
} else {
if (bcount.longValue() + start > stopValue.longValue()) {
done.complete(count);
}
}
} catch (AssertionError | Exception e) {
e.printStackTrace();
done.completeExceptionally(e);
}
});
try {
// start it all up.
replayTestChannel.initialize();
// give a timeout here.
done.get(30, TimeUnit.SECONDS);
// sleep a little to see if more blocks trickle in .. they should not
Thread.sleep(1000);
replayTestChannel.unregisterBlockListener(blockListenerHandle);
// Start 2 and stop is 3 expect 2
final long expectNumber = stopValue.longValue() - start + 1L;
assertEquals(format("Didn't get number we expected %d but got %d block events. Start: %d, end: %d, height: %d", expectNumber, blockEvents.size(), start, stop, stopValue.longValue()), expectNumber, blockEvents.size());
for (long i = stopValue.longValue(); i >= start; i--) {
// make sure all are there.
final BlockEvent blockEvent = blockEvents.get(i);
assertNotNull(format("Missing block event for block number %d. Start= %d", i, start), blockEvent);
}
// light weight test just see if we get reasonable values for traversing the block. Test just whats common between
// Block and FilteredBlock.
int transactionEventCounts = 0;
int chaincodeEventsCounts = 0;
for (long i = stopValue.longValue(); i >= start; i--) {
final BlockEvent blockEvent = blockEvents.get(i);
// out("blockwalker %b, start: %d, stop: %d, i: %d, block %d", useFilteredBlocks, start, stopValue.longValue(), i, blockEvent.getBlockNumber());
// check again
assertEquals(useFilteredBlocks, blockEvent.isFiltered());
if (useFilteredBlocks) {
// should not have raw block event.
assertNull(blockEvent.getBlock());
// should have raw filtered block.
assertNotNull(blockEvent.getFilteredBlock());
} else {
// should not have raw block event.
assertNotNull(blockEvent.getBlock());
// should have raw filtered block.
assertNull(blockEvent.getFilteredBlock());
}
assertEquals(replayTestChannel.getName(), blockEvent.getChannelId());
for (BlockInfo.EnvelopeInfo envelopeInfo : blockEvent.getEnvelopeInfos()) {
if (envelopeInfo.getType() == TRANSACTION_ENVELOPE) {
BlockInfo.TransactionEnvelopeInfo transactionEnvelopeInfo = (BlockInfo.TransactionEnvelopeInfo) envelopeInfo;
// only have valid blocks.
assertTrue(envelopeInfo.isValid());
assertEquals(envelopeInfo.getValidationCode(), 0);
++transactionEventCounts;
for (BlockInfo.TransactionEnvelopeInfo.TransactionActionInfo ta : transactionEnvelopeInfo.getTransactionActionInfos()) {
// out("\nTA:", ta + "\n\n");
ChaincodeEvent event = ta.getEvent();
if (event != null) {
assertNotNull(event.getChaincodeId());
assertNotNull(event.getEventName());
chaincodeEventsCounts++;
}
}
} else {
assertEquals("Only non transaction block should be block 0.", blockEvent.getBlockNumber(), 0);
}
}
}
assertTrue(transactionEventCounts > 0);
if (expectNumber > 4) {
// this should be enough blocks with CC events.
assertTrue(chaincodeEventsCounts > 0);
}
// all done.
replayTestChannel.shutdown(true);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
Aggregations