Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Commit

Permalink
Merge pull request #181 from libp2p/more-integration-tests
Browse files Browse the repository at this point in the history
add more integration tests
  • Loading branch information
marten-seemann committed Oct 27, 2020
2 parents e97576b + 19896cd commit cbcf436
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 42 deletions.
20 changes: 16 additions & 4 deletions .github/workflows/interop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ set -e

SERVER=$1
CLIENT=$2
TEST=$3
SERVER_ADDR="/ip4/127.0.0.1/udp/12345/quic"

for k1 in server*.key; do
for k2 in client*.key; do
echo "Running with server $SERVER ($k1) and client $CLIENT ($k2)"
./$SERVER -role server -key $k1 -peerkey $k2 -addr $SERVER_ADDR &
./$CLIENT -role client -key $k2 -peerkey $k1 -addr $SERVER_ADDR
wait &
if [[ $TEST == "handshake-failure" ]]; then
for k3 in other*.key; do
echo -e "\nRunning with server $SERVER ($k1) and client $CLIENT ($k2). Test: handshake-failure"
./$SERVER -role server -key $k1 -peerkey $k2 -addr $SERVER_ADDR -test handshake-failure &
PID=$!
time ./$CLIENT -role client -key $k2 -peerkey $k3 -addr $SERVER_ADDR -test handshake-failure
kill $PID
wait
done;
else
echo -e "\nRunning with server $SERVER ($k1) and client $CLIENT ($k2). Test: $TEST"
./$SERVER -role server -key $k1 -peerkey $k2 -addr $SERVER_ADDR -test $TEST &
time ./$CLIENT -role client -key $k2 -peerkey $k1 -addr $SERVER_ADDR -test $TEST
wait
fi
done;
done;
30 changes: 21 additions & 9 deletions .github/workflows/interop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
go build -o keygen integrationtests/keygen/keygen.go
./keygen -prefix server
./keygen -prefix client
./keygen -prefix other
- name: Upload keys
uses: actions/upload-artifact@v2
with:
Expand Down Expand Up @@ -57,11 +58,17 @@ jobs:
rm -rf integrationtests || true
mv builder integrationtests
git reflog --decorate -1
if [[ `git merge-base --is-ancestor HEAD 126c64772ba0aef0b2b6d58ff36e55a93f9253a7; echo $?` == "1" ]]; then
go build -o transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} integrationtests/main.go
else
go build -tags oldstream -o transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} integrationtests/main.go
TAGS=()
if [[ `git merge-base --is-ancestor HEAD 126c64772ba0aef0b2b6d58ff36e55a93f9253a7; echo $?` != "1" ]]; then
TAGS+=("oldstream")
fi
if [[ "${{ matrix.cfg.retireBugBackwardsCompatiblityMode }}" == "true" ]]; then
TAGS+=("retirebugcompatmode")
fi
function join { local IFS="$1"; shift; echo "$*"; }
tags=$(join , ${TAGS[@]})
if [[ -n $tags ]]; then tags="-tags $tags"; fi
go build $tags -o transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} integrationtests/main.go
- name: Upload binary
uses: actions/upload-artifact@v2
with:
Expand All @@ -88,8 +95,13 @@ jobs:
with:
name: binary
path: interop/
- name: Run interop
run: |
cd interop
chmod 744 transport*
../.github/workflows/interop.sh transport-go${{ matrix.server.go }}-${{ matrix.server.commit }} transport-go${{ matrix.client.go }}-${{ matrix.client.commit }}
- name: Set permissions
run: chmod 744 interop/transport*
- name: 'Run test case: handshake-failure'
run: cd interop && ../.github/workflows/interop.sh transport-go${{ matrix.server.go }}-${{ matrix.server.commit }} transport-go${{ matrix.client.go }}-${{ matrix.client.commit }} handshake-failure
- name: 'Run test case: single-transfer'
run: cd interop && ../.github/workflows/interop.sh transport-go${{ matrix.server.go }}-${{ matrix.server.commit }} transport-go${{ matrix.client.go }}-${{ matrix.client.commit }} single-transfer
- name: 'Run test case: multi-transfer'
# Longer transfers might fail if the version has the connection ID retirement bug, see https://github.com/ipfs/go-ipfs/issues/7526.
if: ${{ matrix.client.retireBugBackwardsCompatiblityMode || matrix.server.retireBugBackwardsCompatiblityMode }}
run: cd interop && ../.github/workflows/interop.sh transport-go${{ matrix.server.go }}-${{ matrix.server.commit }} transport-go${{ matrix.client.go }}-${{ matrix.client.commit }} multi-transfer
18 changes: 10 additions & 8 deletions .github/workflows/matrix.jsonc
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[
{ "go": "1.13", "commit": "v0.6.0" },
{ "go": "1.14", "commit": "v0.6.0" },
{ "go": "1.13", "commit": "v0.7.0" },
{ "go": "1.14", "commit": "v0.7.0" },
{ "go": "1.13", "commit": "v0.6.0", "retireBugBackwardsCompatiblityMode": false },
{ "go": "1.14", "commit": "v0.6.0", "retireBugBackwardsCompatiblityMode": false },
{ "go": "1.13", "commit": "v0.7.0", "retireBugBackwardsCompatiblityMode": false },
{ "go": "1.14", "commit": "v0.7.0", "retireBugBackwardsCompatiblityMode": false },
{ "go": "1.13", "commit": "v0.7.1", "retireBugBackwardsCompatiblityMode": true },
{ "go": "1.14", "commit": "v0.7.1", "retireBugBackwardsCompatiblityMode": true },
// v0.7.1 was never released in IPFS.
{ "go": "1.14", "commit": "v0.8.0" },
{ "go": "1.15", "commit": "v0.8.0" },
{ "go": "1.14", "commit": "HEAD" },
{ "go": "1.15", "commit": "HEAD" }
{ "go": "1.14", "commit": "v0.8.0", "retireBugBackwardsCompatiblityMode": true },
{ "go": "1.15", "commit": "v0.8.0", "retireBugBackwardsCompatiblityMode": true },
{ "go": "1.14", "commit": "HEAD", "retireBugBackwardsCompatiblityMode": true },
{ "go": "1.15", "commit": "HEAD", "retireBugBackwardsCompatiblityMode": true }
]
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ require (
github.com/onsi/ginkgo v1.14.0
github.com/onsi/gomega v1.10.1
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
)
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
129 changes: 108 additions & 21 deletions integrationtests/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/transport"
libp2pquic "github.com/libp2p/go-libp2p-quic-transport"
ma "github.com/multiformats/go-multiaddr"
"golang.org/x/sync/errgroup"

"github.com/libp2p/go-libp2p-quic-transport/integrationtests/stream"
)
Expand All @@ -23,6 +25,7 @@ func main() {
hostKeyFile := flag.String("key", "", "file containing the libp2p private key")
peerKeyFile := flag.String("peerkey", "", "file containing the libp2p private key of the peer")
addrStr := flag.String("addr", "", "address to listen on (for the server) or to dial (for the client)")
test := flag.String("test", "", "test name")
role := flag.String("role", "", "server or client")
flag.Parse()

Expand All @@ -37,11 +40,11 @@ func main() {

switch *role {
case "server":
if err := runServer(hostKey, peerPubKey, addr); err != nil {
if err := runServer(hostKey, peerPubKey, addr, *test); err != nil {
log.Fatal(err)
}
case "client":
if err := runClient(hostKey, peerPubKey, addr); err != nil {
if err := runClient(hostKey, peerPubKey, addr, *test); err != nil {
log.Fatal(err)
}
}
Expand Down Expand Up @@ -72,7 +75,7 @@ func readKeys(hostKeyFile, peerKeyFile string) (crypto.PrivKey, crypto.PubKey, e
return hostKey, peerKey.GetPublic(), nil
}

func runServer(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr) error {
func runServer(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr, test string) error {
tr, err := libp2pquic.NewTransport(hostKey, nil, nil)
if err != nil {
return err
Expand All @@ -85,6 +88,9 @@ func runServer(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr)
if err != nil {
return err
}
if test == "handshake-failure" {
return errors.New("didn't expect to accept a connection in the handshake-failure test")
}
defer ln.Close()
if !conn.RemotePublicKey().Equals(peerKey) {
return errors.New("mismatching public keys")
Expand All @@ -96,43 +102,60 @@ func runServer(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr)
if conn.RemotePeer() != clientPeerID {
return fmt.Errorf("remote Peer ID mismatch. Got %s, expected %s", conn.RemotePeer().Pretty(), clientPeerID.Pretty())
}
var g errgroup.Group
for {
st, err := conn.AcceptStream()
if err != nil {
return nil
break
}
str := stream.WrapStream(st)
defer str.Close()
data, err := ioutil.ReadAll(str)
if err != nil {
return err
}
if _, err := str.Write(data); err != nil {
return err
}
if err := str.CloseWrite(); err != nil {
return err
}
}
g.Go(func() error {
data, err := ioutil.ReadAll(str)
if err != nil {
return err
}
if err := str.CloseRead(); err != nil {
return err
}
if _, err := str.Write(data); err != nil {
return err
}
return str.CloseWrite()
})
}
return g.Wait()
}

func runClient(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr) error {
func runClient(hostKey crypto.PrivKey, serverKey crypto.PubKey, addr ma.Multiaddr, test string) error {
tr, err := libp2pquic.NewTransport(hostKey, nil, nil)
if err != nil {
return err
}
serverPeerID, err := peer.IDFromPublicKey(peerKey)
switch test {
case "single-transfer":
return testSingleFileTransfer(tr, serverKey, addr)
case "multi-transfer":
return testMultipleFileTransfer(tr, serverKey, addr)
case "handshake-failure":
return testHandshakeFailure(tr, serverKey, addr)
default:
return errors.New("unknown test")
}
}

func testSingleFileTransfer(tr transport.Transport, serverKey crypto.PubKey, addr ma.Multiaddr) error {
serverPeerID, err := peer.IDFromPublicKey(serverKey)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
conn, err := tr.Dial(ctx, addr, serverPeerID)
if err != nil {
return err
return fmt.Errorf("Dial failed: %w", err)
}
defer conn.Close()
if !conn.RemotePublicKey().Equals(peerKey) {
if !conn.RemotePublicKey().Equals(serverKey) {
return errors.New("mismatching public keys")
}
if conn.RemotePeer() != serverPeerID {
Expand Down Expand Up @@ -160,3 +183,67 @@ func runClient(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr)
}
return nil
}

func testMultipleFileTransfer(tr transport.Transport, serverKey crypto.PubKey, addr ma.Multiaddr) error {
serverPeerID, err := peer.IDFromPublicKey(serverKey)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
conn, err := tr.Dial(ctx, addr, serverPeerID)
if err != nil {
return fmt.Errorf("Dial failed: %w", err)
}
defer conn.Close()
if !conn.RemotePublicKey().Equals(serverKey) {
return errors.New("mismatching public keys")
}
if conn.RemotePeer() != serverPeerID {
return fmt.Errorf("remote Peer ID mismatch. Got %s, expected %s", conn.RemotePeer().Pretty(), serverPeerID.Pretty())
}
var g errgroup.Group
for i := 0; i < 2000; i++ {
g.Go(func() error {
st, err := conn.OpenStream()
if err != nil {
return err
}
str := stream.WrapStream(st)
data := make([]byte, 1<<9)
rand.Read(data)
if _, err := str.Write(data); err != nil {
return err
}
if err := str.CloseWrite(); err != nil {
return err
}
echoed, err := ioutil.ReadAll(str)
if err != nil {
return err
}
if !bytes.Equal(data, echoed) {
return errors.New("echoed data does not match")
}
return nil
})
}
return g.Wait()
}

func testHandshakeFailure(tr transport.Transport, serverKey crypto.PubKey, addr ma.Multiaddr) error {
serverPeerID, err := peer.IDFromPublicKey(serverKey)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
_, err = tr.Dial(ctx, addr, serverPeerID)
if err == nil {
return errors.New("expected the handshake to fail")
}
if err.Error() != "CRYPTO_ERROR: peer IDs don't match" {
return fmt.Errorf("got unexpected error: %s", err.Error())
}
return nil
}

0 comments on commit cbcf436

Please sign in to comment.