1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
//go:build go1.18
// +build go1.18
package app_test
// import (
// "context"
// "crypto/tls"
// "net"
// "testing"
// "github.com/canonical/go-dqlite/v2/app"
// "github.com/canonical/go-dqlite/v2/client"
// "github.com/quic-go/quic-go"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/require"
// )
// // quic.Stream doesn't implement net.Conn, so we need to wrap it.
// type quicConn struct {
// quic.Stream
// }
// func (c *quicConn) LocalAddr() net.Addr {
// return nil
// }
// func (c *quicConn) RemoteAddr() net.Addr {
// return nil
// }
// // TestExternalConnWithQUIC creates a 3-member cluster using external quic connection
// // and ensures the cluster is successfully created, and that the connection is
// // handled manually.
// func TestExternalConnWithQUIC(t *testing.T) {
// externalAddr1 := "127.0.0.1:9191"
// externalAddr2 := "127.0.0.1:9292"
// externalAddr3 := "127.0.0.1:9393"
// acceptCh1 := make(chan net.Conn)
// acceptCh2 := make(chan net.Conn)
// acceptCh3 := make(chan net.Conn)
// dialFunc := func(ctx context.Context, addr string) (net.Conn, error) {
// conn, err := quic.DialAddrContext(ctx, addr, &tls.Config{InsecureSkipVerify: true, NextProtos: []string{"quic"}}, nil)
// require.NoError(t, err)
// stream, err := conn.OpenStreamSync(ctx)
// require.NoError(t, err)
// return &quicConn{
// Stream: stream,
// }, nil
// }
// cert, pool := loadCert(t)
// tlsconfig := app.SimpleListenTLSConfig(cert, pool)
// tlsconfig.NextProtos = []string{"quic"}
// tlsconfig.ClientAuth = tls.NoClientCert
// serveQUIC := func(addr string, acceptCh chan net.Conn, cleanups chan func()) {
// lis, err := quic.ListenAddr(addr, tlsconfig, nil)
// require.NoError(t, err)
// ctx, cancel := context.WithCancel(context.Background())
// go func() {
// for {
// select {
// case <-ctx.Done():
// return
// default:
// conn, err := lis.Accept(context.Background())
// if err != nil {
// return
// }
// stream, err := conn.AcceptStream(context.Background())
// if err != nil {
// return
// }
// acceptCh <- &quicConn{
// Stream: stream,
// }
// }
// }
// }()
// cleanup := func() {
// cancel()
// require.NoError(t, lis.Close())
// }
// cleanups <- cleanup
// }
// liscleanups := make(chan func(), 3)
// // Start up three listeners.
// go serveQUIC(externalAddr1, acceptCh1, liscleanups)
// go serveQUIC(externalAddr2, acceptCh2, liscleanups)
// go serveQUIC(externalAddr3, acceptCh3, liscleanups)
// defer func() {
// for i := 0; i < 3; i++ {
// cleanup := <-liscleanups
// cleanup()
// }
// close(liscleanups)
// }()
// app1, cleanup := newAppWithNoTLS(t, app.WithAddress(externalAddr1), app.WithExternalConn(dialFunc, acceptCh1))
// defer cleanup()
// app2, cleanup := newAppWithNoTLS(t, app.WithAddress(externalAddr2), app.WithExternalConn(dialFunc, acceptCh2), app.WithCluster([]string{externalAddr1}))
// defer cleanup()
// require.NoError(t, app2.Ready(context.Background()))
// app3, cleanup := newAppWithNoTLS(t, app.WithAddress(externalAddr3), app.WithExternalConn(dialFunc, acceptCh3), app.WithCluster([]string{externalAddr1}))
// defer cleanup()
// require.NoError(t, app3.Ready(context.Background()))
// // Get a client from the first node (likely the leader).
// cli, err := app1.Leader(context.Background())
// require.NoError(t, err)
// defer cli.Close()
// // Ensure entries exist for each cluster member.
// cluster, err := cli.Cluster(context.Background())
// require.NoError(t, err)
// assert.Equal(t, externalAddr1, cluster[0].Address)
// assert.Equal(t, externalAddr2, cluster[1].Address)
// assert.Equal(t, externalAddr3, cluster[2].Address)
// // Every cluster member should be a voter.
// assert.Equal(t, client.Voter, cluster[0].Role)
// assert.Equal(t, client.Voter, cluster[1].Role)
// assert.Equal(t, client.Voter, cluster[2].Role)
// }
|