Skip to content

Define a proper base class for fixture tests#2286

Merged
pm47 merged 15 commits into
masterfrom
simple-integration
Jun 3, 2022
Merged

Define a proper base class for fixture tests#2286
pm47 merged 15 commits into
masterfrom
simple-integration

Conversation

@pm47
Copy link
Copy Markdown
Member

@pm47 pm47 commented May 27, 2022

This PR does two main things:

  • introduce a new FixtureSpec base class for tests that involve a fixture. See the scaladoc for more info. The existing test WaitForOpenChannelStateSpec has been migrated as an example. The diff is small but we separate clearly the fixtures from the test framework. There is duplication for now, but the goal is for ChannelStateTestsHelperMethods to disappear.
  • add new simple integration tests in package integration.basic. They are based on MinimalNodeFixture, which is a full setup for a node with real actors, except the bitcoin part (watcher/wallet) which is mocked. They are much lighter than our previous integration tests, which allow us to keep each test individual, as opposed to having all tests of the same suite depend on each other. We can define more complex fixtures with any number of nodes.

Also updated scalatest version and fixed a few issues.

@pm47 pm47 requested a review from t-bast May 27, 2022 17:27
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

Merging #2286 (2e6e566) into master (44e7127) will decrease coverage by 0.03%.
The diff coverage is 82.35%.

@@            Coverage Diff             @@
##           master    #2286      +/-   ##
==========================================
- Coverage   84.40%   84.36%   -0.04%     
==========================================
  Files         194      194              
  Lines       14411    14419       +8     
  Branches      567      581      +14     
==========================================
+ Hits        12163    12164       +1     
- Misses       2248     2255       +7     
Impacted Files Coverage Δ
...main/scala/fr/acinq/eclair/io/PeerConnection.scala 85.55% <50.00%> (-0.43%) ⬇️
...air-core/src/main/scala/fr/acinq/eclair/Logs.scala 83.33% <100.00%> (+0.28%) ⬆️
...in/scala/fr/acinq/eclair/channel/fsm/Channel.scala 88.39% <100.00%> (+0.11%) ⬆️
...-core/src/main/scala/fr/acinq/eclair/io/Peer.scala 90.41% <100.00%> (ø)
...in/scala/fr/acinq/eclair/io/ReconnectionTask.scala 98.07% <100.00%> (+1.92%) ⬆️
...src/main/scala/fr/acinq/eclair/router/Router.scala 93.78% <100.00%> (+0.03%) ⬆️
...q/eclair/channel/publish/ReplaceableTxFunder.scala 86.91% <0.00%> (-3.67%) ⬇️
...src/main/scala/fr/acinq/eclair/db/pg/PgUtils.scala 89.39% <0.00%> (-1.52%) ⬇️
...cinq/eclair/payment/receive/MultiPartHandler.scala 93.61% <0.00%> (-1.42%) ⬇️
... and 4 more

Copy link
Copy Markdown
Member

@t-bast t-bast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the direction in which we're going with that change, and I'm happy to merge that PR and start using these new fixtures for new code, but before migrating old code or removing ChannelStateTestHelperMethods we should really integrate dual-funding which touches those a lot, otherwise we'll make a complex set of PRs even more complex to integrate!

Comment on lines +44 to +47
override def makeFundingTx(pubkeyScript: ByteVector, amount: Satoshi, feeRatePerKw: FeeratePerKw)(implicit ec: ExecutionContext): Future[MakeFundingTxResponse] = {
val tx = DummyOnChainWallet.makeDummyFundingTx(pubkeyScript, amount)
funded += (tx.fundingTx.txid -> tx.fundingTx)
Future.successful(tx)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm making many changes to these test helpers in #2275, if you plan on making more changes here in follow-up PRs we should probably do it after dual-funding to minimize conflicts.

Copy link
Copy Markdown
Member Author

@pm47 pm47 May 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, I don't plan to make more changes so we should be fine. Dealing with the mempool/blockchain is one of the trickiest parts, because they need to be shared among various MinimalNodeFixture. I have explored several approaches and am still not 100% happy.

In particular, there are two ways of confirming channels: MinimalNodeFixture.confirmChannel and MinimalNodeFixture.autoConfirmLocalChannels. I think the latter (based on autopilot) is nicer when you don't need fine-grained control, but the core issue of having access to the actual transaction remains. For example, note that we pass a reference to alice's wallet for bob's autopilot:

bob.watcher.setAutoPilot(autoConfirmLocalChannels(alice.wallet.funded))

Maybe with dual-funding this will be a tad simpler since both sides know the full tx?

@pm47
Copy link
Copy Markdown
Member Author

pm47 commented May 30, 2022

I like the direction in which we're going with that change, and I'm happy to merge that PR and start using these new fixtures for new code, but before migrating old code or removing ChannelStateTestHelperMethods we should really integrate dual-funding which touches those a lot, otherwise we'll make a complex set of PRs even more complex to integrate!

The WaitForOpenChannelStateSpec migration doesn't bring much by itself. I can either revert it, or migrate all other tests. It might be worth it to migrate the rest because it should reduce resource consumption, but OTOH maybe better to do it properly in a dedicated PR and take the time to improve the migrated tests. Or I can do a quick migration and we improve them later. WDYT?

edit: On 2nd thought, maybe better to wait for the akka typed migration before revamping the channel tests.

* Created by PM on 11/03/2020.
*/
class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef) extends FSMDiagnosticActorLogging[PeerConnection.State, PeerConnection.Data] {
class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef) extends FSMDiagnosticActorLogging[PeerConnection.State, PeerConnection.Data] with Stash {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another pretty good reason not to use TestActorRef is that it is not compatible with Stash (https://stackoverflow.com/a/18377939).

Stash allows us to nicely handle race conditions between messages, instead of delaying them, which creates other race conditions (which is exactly what happened in my attempted fix 2632be3).

}
d.transport ! localInit
startSingleTimer(INIT_TIMER, InitTimeout, conf.initTimeout)
unstashAll() // unstash remote init if it already arrived
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NB: I'm only unstashing right before we are ready to process the remote init.

@pm47 pm47 requested a review from t-bast May 30, 2022 12:38
@t-bast
Copy link
Copy Markdown
Member

t-bast commented May 31, 2022

It might be worth it to migrate the rest because it should reduce resource consumption, but OTOH maybe better to do it properly in a dedicated PR and take the time to improve the migrated tests. Or I can do a quick migration and we improve them later. WDYT?

If we can delay the migration of the channel tests just after we do dual funding, that would be great :)
Let's get this PR merged and the new fixtures used for new tests, and we start migrating old tests right after we've dealt with dual funding?

@pm47
Copy link
Copy Markdown
Member Author

pm47 commented Jun 1, 2022

If we can delay the migration of the channel tests just after we do dual funding, that would be great :)

Agreed, done in fb2e439.

pm47 added 3 commits June 1, 2022 17:35
The circular dependency to TestKitBaseClass/TestKitBase was really
weird, we had:
- NormalStateSpec -> TestKitBaseClass -> ChannelStateTestsBase
- ChannelStateTestsBase -> ChannelStateTestsHelperMethods
- ChannelStateTestsHelperMethods -> TestKitBase
Triple equals allows customizing the equality method, but we never use
that.

Detailed errors (which is what we were looking for) are provided by
mixing in scalatest's `Assertions` and using the regular `assert(x==y)`
syntax. The `Assertions` trait is already mixed in by default in all
scalatest suites.
Copy link
Copy Markdown
Member Author

@pm47 pm47 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some cleanup which shouldn't impact your dual-funding tests.

bob2blockchain.expectMsgType[WatchFundingDeeplyBuried]
awaitCond(alice.stateName == NORMAL)
awaitCond(bob.stateName == NORMAL)
eventually(assert(alice.stateName == NORMAL))
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

assertion failed: timeout 149050696200 nanoseconds expired: 
java.lang.AssertionError: assertion failed: timeout 149050696200 nanoseconds expired:

After:

The code passed to eventually never returned normally. Attempted 9 times over 161.3674 milliseconds. Last failure message: NORMAL did not equal CLOSED.
ScalaTestFailureLocation: fr.acinq.eclair.channel.states.ChannelStateTestsHelperMethods at (ChannelStateTestsHelperMethods.scala:245)
Expected :CLOSED.
Actual   :The code passed to eventually never returned normally. Attempted 9 times over 161.3674 milliseconds. Last failure message: NORMAL

No comment!

@pm47 pm47 merged commit 9610fe3 into master Jun 3, 2022
@pm47 pm47 deleted the simple-integration branch June 3, 2022 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants