Skip to content

Commit

Permalink
Fix Flash failure on CI test
Browse files Browse the repository at this point in the history
The unittests in `agora.test.Flash` fails often on CI because there is
a timing issue. Unittests expect `update_tx`s not to be sent as soon as
a block is externalized when the `allow_publish` is set to `false`. But
the `update_tx` is sent as soon as the `allow_publish` is to set `true`
by calling `setPublishEnable`, which is not to be supposed to be sent.
  • Loading branch information
linked0 committed Feb 10, 2022
1 parent 975bcc5 commit 2502743
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
7 changes: 3 additions & 4 deletions source/agora/flash/Channel.d
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,6 @@ LOuter: while (1)

public void onUpdateTxExternalized (in Transaction tx, in uint utxo_idx, in bool is_last)
{
this.state = ChannelState.StartedUnilateralClose;
this.onChannelNotify(this.own_pk, this.conf.chan_id, this.state,
ErrorCode.None);

this.last_externalized_update_utxo = UTXO.getHash(tx.hashFull(), utxo_idx);
if (is_last)
{
Expand All @@ -754,6 +750,9 @@ LOuter: while (1)
else
{
this.publishUpdateTx(this.channel_updates[$ - 1]);
this.state = ChannelState.StartedUnilateralClose;
this.onChannelNotify(this.own_pk, this.conf.chan_id, this.state,
ErrorCode.None, this.height);
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/agora/flash/Node.d
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ public class FlashNode : FlashControlAPI
if (state == ChannelState.Open) // todo: might not exist
this.onChannelOpen(reg_pk, this.channels[chan_id].conf, height);

this.listener.onChannelNotify(reg_pk, chan_id, state, error);
this.listener.onChannelNotify(reg_pk, chan_id, state, error, height);
}

///
Expand Down
43 changes: 33 additions & 10 deletions source/agora/test/Flash.d
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ public interface TestFlashListenerAPI : FlashListenerAPI
/// has succeeded / failed, and return true / false for success
ErrorCode waitUntilNotified (Invoice);

/// wait until we get a notification about the given channel state,
/// and return any associated error codes
ErrorCode waitUntilChannelState (Hash, ChannelState, PublicKey node = PublicKey.init);
/// wait until we get a notification about the given channel state
/// with the specified height and return any associated error codes
ErrorCode waitUntilChannelState (Hash, ChannelState, PublicKey node = PublicKey.init,
Height height = Height(0), bool erase_state = true);

/// Print out the contents of the log
public void printLog ();
Expand Down Expand Up @@ -498,6 +499,7 @@ private class FlashListener : TestFlashListenerAPI
{
ChannelState state;
ErrorCode error;
Height update_height;
}

State[PublicKey][Hash] channel_state;
Expand Down Expand Up @@ -541,36 +543,51 @@ private class FlashListener : TestFlashListenerAPI
}

public ErrorCode waitUntilChannelState (Hash chan_id, ChannelState state,
PublicKey node = PublicKey.init)
PublicKey node = PublicKey.init, Height height = Height(0),
bool erase_state = true)
{
scope (exit) this.channel_state.remove(chan_id);
// There is no case where we check the state with a specified
// height and no public key.
assert(height == Height(0) || node != PublicKey.init);

scope (exit) if (erase_state) this.channel_state.remove(chan_id);
while (1)
{
if (auto chan_states = chan_id in this.channel_state)
{
if (auto chan_state = node in *chan_states)
{
if ((*chan_state).state >= state)
return (*chan_state).error;
{
if (height == Height(0))
return (*chan_state).error;
else if ((*chan_state).update_height >= height)
return (*chan_state).error;
}
}
if (node == PublicKey.init)
{
auto states = chan_states.byValue
.filter!(chan_state => chan_state.state >= state);
if (!states.empty())
return states.front.error;
}

}

this.taskman.wait(200.msecs);
}
}

public void onChannelNotify (PublicKey pk, Hash chan_id, ChannelState state,
ErrorCode error, Height = Height(0))
ErrorCode error, Height height = Height(0))
{
log.info("Channel event {}, id {}", state, chan_id.flashPrettify);
log.info("{}: Channel event {}, id {}, height {}", pk.flashPrettify, state, chan_id.flashPrettify,
height);
if (chan_id !in this.channel_state)
this.channel_state[chan_id] = typeof(this.channel_state[chan_id]).init;
this.channel_state[chan_id][pk] = State(state, error);

this.channel_state[chan_id][pk] = State(state, error, height);
}

public Result!ChannelUpdate onRequestedChannelOpen (PublicKey pk, ChannelConfig conf)
Expand Down Expand Up @@ -1913,7 +1930,6 @@ unittest
network.listener.waitUntilChannelState(chan_id,
ChannelState.StartedUnilateralClose);


// publish an older update
update_tx = alice.getPublishUpdateIndex(WK.Keys.A.address, chan_id, 2);
network.postAndEnsureTxInPool(update_tx);
Expand All @@ -1924,6 +1940,13 @@ unittest
network.clients[0].postTransaction(update_tx);
assert(!network.clients[0].hasTransactionHash(update_tx.hashFull()));

// wait until all the flash nodes skip publishing `update tx` before
// the `setPublishEnable` is called.
network.listener.waitUntilChannelState(chan_id,
ChannelState.StartedUnilateralClose, WK.Keys.A.address, Height(4), false);
network.listener.waitUntilChannelState(chan_id,
ChannelState.StartedUnilateralClose, WK.Keys.C.address, Height(4));

// allow normal node operation again
alice.setPublishEnable(true);
charlie.setPublishEnable(true);
Expand Down
2 changes: 1 addition & 1 deletion submodules/localrest

0 comments on commit 2502743

Please sign in to comment.