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

Reenable ServerSocket tests #1777

Merged
merged 1 commit into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ import org.scalatest.funsuite.FixtureAnyFunSuiteLike
import org.scalatest.{Outcome, ParallelTestExecution, Tag}
import scodec.bits.ByteVector

import java.net.{ServerSocket, Socket}
import java.util.concurrent.Executors
import java.net.InetSocketAddress
import java.nio.channels.ServerSocketChannel
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}

class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with ParallelTestExecution {

import PeerSpec._

val fakeIPAddress: NodeAddress = NodeAddress.fromParts("1.2.3.4", 42000).get

case class FixtureParam(nodeParams: NodeParams, remoteNodeId: PublicKey, peer: TestFSMRef[Peer.State, Peer.Data, Peer], peerConnection: TestProbe, channel: TestProbe)
Expand Down Expand Up @@ -106,41 +107,35 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
probe.expectMsg(PeerConnection.ConnectionResult.NoAddressFound)
}

ignore("successfully connect to peer at user request") { f =>
test("successfully connect to peer at user request") { f =>
import f._

// this actor listens to connection requests and creates connections
system.actorOf(ClientSpawner.props(nodeParams.keyPair, nodeParams.socksProxy_opt, nodeParams.peerConnectionConf, TestProbe().ref, TestProbe().ref))

// we create a dummy tcp server and update bob's announcement to point to it
val mockServer = new ServerSocket(0, 1) // port will be assigned automatically
val mockAddress = HostAndPort.fromParts(mockServer.getInetAddress.getHostAddress, mockServer.getLocalPort)
val (mockServer, serverAddress) = createMockServer()
val mockAddress = HostAndPort.fromParts(serverAddress.getHostName, serverAddress.getPort)

val probe = TestProbe()
probe.send(peer, Peer.Init(Set.empty))
// we have auto-reconnect=false so we need to manually tell the peer to reconnect
probe.send(peer, Peer.Connect(remoteNodeId, Some(mockAddress)))

// assert our mock server got an incoming connection (the client was spawned with the address from node_announcement)
val res = TestProbe()
Future {
val socket = mockServer.accept()
res.ref ! socket
}(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(1)))
res.expectMsgType[Socket](10 seconds)

awaitCond(mockServer.accept() != null, max = 30 seconds, interval = 1 second)
mockServer.close()
}

ignore("successfully reconnect to peer at startup when there are existing channels", Tag("auto_reconnect")) { f =>
test("successfully reconnect to peer at startup when there are existing channels", Tag("auto_reconnect")) { f =>
import f._

// this actor listens to connection requests and creates connections
system.actorOf(ClientSpawner.props(nodeParams.keyPair, nodeParams.socksProxy_opt, nodeParams.peerConnectionConf, TestProbe().ref, TestProbe().ref))

// we create a dummy tcp server and update bob's announcement to point to it
val mockServer = new ServerSocket(0, 1) // port will be assigned automatically
val mockAddress = NodeAddress.fromParts(mockServer.getInetAddress.getHostAddress, mockServer.getLocalPort).get
val (mockServer, serverAddress) = createMockServer()
val mockAddress = NodeAddress.fromParts(serverAddress.getHostName, serverAddress.getPort).get

// we put the server address in the node db
val ann = NodeAnnouncement(randomBytes64, Features.empty, 1, Bob.nodeParams.nodeId, Color(100.toByte, 200.toByte, 300.toByte), "node-alias", mockAddress :: Nil)
Expand All @@ -150,13 +145,7 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
probe.send(peer, Peer.Init(Set(ChannelCodecsSpec.normal)))

// assert our mock server got an incoming connection (the client was spawned with the address from node_announcement)
val res = TestProbe()
Future {
val socket = mockServer.accept()
res.ref ! socket
}(ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(1)))
res.expectMsgType[Socket](10 seconds)

awaitCond(mockServer.accept() != null, max = 30 seconds, interval = 1 second)
mockServer.close()
}

Expand Down Expand Up @@ -379,3 +368,15 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
assert(init.pushAmount === 100.msat)
}
}

object PeerSpec {

def createMockServer(): (ServerSocketChannel, InetSocketAddress) = {
val mockServer = ServerSocketChannel.open()
// NB: we force 127.0.0.1 (IPv4) because there are issues on ubuntu build machines with IPv6 loopback
mockServer.bind(new InetSocketAddress("127.0.0.1", 0))
mockServer.configureBlocking(false)
Copy link
Member

Choose a reason for hiding this comment

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

configureBlocking(false) ❤️

Copy link
Member Author

Choose a reason for hiding this comment

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

I discovered that one while I was thinking that the issue was a deadlock on the server. It didn't fix the build, but it's still an improvement 😃

(mockServer, mockServer.getLocalAddress.asInstanceOf[InetSocketAddress])
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import fr.acinq.eclair.wire.protocol.{Color, NodeAddress, NodeAnnouncement}
import org.scalatest.funsuite.FixtureAnyFunSuiteLike
import org.scalatest.{Outcome, ParallelTestExecution, Tag}

import java.net.ServerSocket
import scala.concurrent.duration._

class ReconnectionTaskSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with ParallelTestExecution {
Expand Down Expand Up @@ -218,12 +217,12 @@ class ReconnectionTaskSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike

}

ignore("reconnect using the address from node_announcement") { f =>
test("reconnect using the address from node_announcement") { f =>
import f._

// we create a dummy tcp server and update bob's announcement to point to it
val mockServer = new ServerSocket(0, 1) // port will be assigned automatically
val mockAddress = NodeAddress.fromParts(mockServer.getInetAddress.getHostAddress, mockServer.getLocalPort).get
val (mockServer, serverAddress) = PeerSpec.createMockServer()
val mockAddress = NodeAddress.fromParts(serverAddress.getHostName, serverAddress.getPort).get
val bobAnnouncement = NodeAnnouncement(randomBytes64, Features.empty, 1, remoteNodeId, Color(100.toByte, 200.toByte, 300.toByte), "node-alias", mockAddress :: Nil)
nodeParams.db.network.addNode(bobAnnouncement)

Expand All @@ -232,11 +231,8 @@ class ReconnectionTaskSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
peer.send(reconnectionTask, Peer.Connect(remoteNodeId, None))

// assert our mock server got an incoming connection (the client was spawned with the address from node_announcement)
within(30 seconds) {
mockServer.accept()
}
awaitCond(mockServer.accept() != null, max = 30 seconds, interval = 1 second)
mockServer.close()
}


}