2021-02-09 11:53:33 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2021-01-25 12:23:03 +00:00
|
|
|
package go_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/rand"
|
2021-01-26 17:33:29 +00:00
|
|
|
"fmt"
|
2021-01-25 12:23:03 +00:00
|
|
|
"testing"
|
2021-01-25 15:35:22 +00:00
|
|
|
"time"
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
"github.com/ssb-ngi-pointer/go-ssb-room/roomdb"
|
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2021-01-25 12:23:03 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2021-01-25 15:35:22 +00:00
|
|
|
"go.cryptoscope.co/muxrpc/v2"
|
2021-01-25 12:23:03 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
|
2021-02-09 16:38:51 +00:00
|
|
|
"github.com/ssb-ngi-pointer/go-ssb-room/roomsrv"
|
2021-02-11 15:43:19 +00:00
|
|
|
refs "go.mindeco.de/ssb-refs"
|
2021-01-25 12:23:03 +00:00
|
|
|
)
|
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
type testBot struct {
|
|
|
|
Server *roomsrv.Server
|
|
|
|
Members roomdb.MembersService
|
|
|
|
}
|
|
|
|
|
|
|
|
func createServerAndBots(t *testing.T, ctx context.Context, count uint) []testBot {
|
2021-01-25 15:35:22 +00:00
|
|
|
testInit(t)
|
2021-01-26 17:33:29 +00:00
|
|
|
r := require.New(t)
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
botgroup, ctx := errgroup.WithContext(ctx)
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
bs := newBotServer(ctx, mainLog)
|
2021-01-25 12:23:03 +00:00
|
|
|
|
|
|
|
appKey := make([]byte, 32)
|
|
|
|
rand.Read(appKey)
|
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
netOpts := []roomsrv.Option{
|
2021-01-25 12:23:03 +00:00
|
|
|
roomsrv.WithAppKey(appKey),
|
|
|
|
roomsrv.WithContext(ctx),
|
|
|
|
}
|
2021-03-19 10:51:06 +00:00
|
|
|
theBots := []testBot{}
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
srvsMembers, serv := makeNamedTestBot(t, "srv", netOpts)
|
2021-01-25 15:35:22 +00:00
|
|
|
botgroup.Go(bs.Serve(serv))
|
2021-03-19 10:51:06 +00:00
|
|
|
theBots = append(theBots, testBot{
|
|
|
|
Server: serv,
|
|
|
|
Members: srvsMembers,
|
|
|
|
})
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-26 17:33:29 +00:00
|
|
|
for i := uint(1); i < count+1; i++ {
|
2021-03-19 10:51:06 +00:00
|
|
|
botMembers, botSrv := makeNamedTestBot(t, fmt.Sprintf("%d", i), netOpts)
|
|
|
|
botgroup.Go(bs.Serve(botSrv))
|
|
|
|
theBots = append(theBots, testBot{
|
|
|
|
Server: botSrv,
|
|
|
|
Members: botMembers,
|
|
|
|
})
|
2021-01-26 17:33:29 +00:00
|
|
|
}
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-26 17:33:29 +00:00
|
|
|
t.Cleanup(func() {
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
for _, bot := range theBots {
|
2021-03-19 10:51:06 +00:00
|
|
|
bot.Server.Shutdown()
|
|
|
|
r.NoError(bot.Server.Close())
|
2021-01-26 17:33:29 +00:00
|
|
|
}
|
|
|
|
r.NoError(botgroup.Wait())
|
|
|
|
})
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-26 17:33:29 +00:00
|
|
|
return theBots
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTunnelServerSimple(t *testing.T) {
|
|
|
|
// defer leakcheck.Check(t)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
theBots := createServerAndBots(t, ctx, 2)
|
|
|
|
|
|
|
|
r := require.New(t)
|
|
|
|
a := assert.New(t)
|
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
serv := theBots[0].Server
|
|
|
|
botA := theBots[1].Server
|
|
|
|
botB := theBots[2].Server
|
2021-01-25 15:35:22 +00:00
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
// allow both clients
|
2021-03-29 08:23:03 +00:00
|
|
|
theBots[0].Members.Add(ctx, botA.Whoami(), roomdb.RoleMember)
|
|
|
|
theBots[0].Members.Add(ctx, botB.Whoami(), roomdb.RoleMember)
|
2021-01-25 15:35:22 +00:00
|
|
|
|
|
|
|
// allow bots to dial the remote
|
2021-03-29 08:23:03 +00:00
|
|
|
theBots[1].Members.Add(ctx, serv.Whoami(), roomdb.RoleMember)
|
|
|
|
theBots[2].Members.Add(ctx, serv.Whoami(), roomdb.RoleMember)
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
// dial up B->A and C->A
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
// should work (we allowed A)
|
|
|
|
err := botA.Network.Connect(ctx, serv.Network.GetListenAddr())
|
|
|
|
r.NoError(err, "connect A to the Server")
|
2021-01-25 12:23:03 +00:00
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
// shouldn't work (we did not allowed A)
|
|
|
|
err = botB.Network.Connect(ctx, serv.Network.GetListenAddr())
|
|
|
|
r.NoError(err, "connect B to the Server") // we dont see an error because it just establishes the tcp connection
|
|
|
|
|
2021-01-25 17:31:09 +00:00
|
|
|
// t.Log("letting handshaking settle..")
|
|
|
|
// time.Sleep(1 * time.Second)
|
2021-01-25 15:35:22 +00:00
|
|
|
|
|
|
|
var srvWho struct {
|
|
|
|
ID refs.FeedRef
|
|
|
|
}
|
|
|
|
|
|
|
|
edpOfB, has := botB.Network.GetEndpointFor(serv.Whoami())
|
|
|
|
r.False(has, "botB has an endpoint for the server!")
|
|
|
|
if edpOfB != nil {
|
2021-01-25 17:31:09 +00:00
|
|
|
a.Nil(edpOfB, "should not have an endpoint on B")
|
2021-01-25 15:35:22 +00:00
|
|
|
err = edpOfB.Async(ctx, &srvWho, muxrpc.TypeJSON, muxrpc.Method{"whoami"})
|
|
|
|
r.Error(err)
|
|
|
|
t.Log(srvWho.ID.Ref())
|
|
|
|
}
|
|
|
|
|
2021-01-25 17:31:09 +00:00
|
|
|
edpOfA, has := botA.Network.GetEndpointFor(serv.Whoami())
|
|
|
|
r.True(has, "botA has no endpoint for the server")
|
|
|
|
|
|
|
|
err = edpOfA.Async(ctx, &srvWho, muxrpc.TypeJSON, muxrpc.Method{"whoami"})
|
|
|
|
r.NoError(err)
|
|
|
|
|
|
|
|
t.Log("server whoami:", srvWho.ID.Ref())
|
|
|
|
a.True(serv.Whoami().Equal(&srvWho.ID))
|
|
|
|
|
|
|
|
// start testing basic room stuff
|
|
|
|
var yes bool
|
|
|
|
err = edpOfA.Async(ctx, &yes, muxrpc.TypeJSON, muxrpc.Method{"tunnel", "isRoom"})
|
|
|
|
r.NoError(err)
|
|
|
|
a.True(yes, "srv is not a room?!")
|
|
|
|
|
|
|
|
var ts int
|
|
|
|
err = edpOfA.Async(ctx, &ts, muxrpc.TypeJSON, muxrpc.Method{"tunnel", "ping"})
|
|
|
|
r.NoError(err)
|
|
|
|
t.Log("ping:", ts)
|
|
|
|
|
2021-01-25 15:35:22 +00:00
|
|
|
// cleanup
|
|
|
|
cancel()
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRoomAnnounce(t *testing.T) {
|
|
|
|
// defer leakcheck.Check(t)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
theBots := createServerAndBots(t, ctx, 2)
|
|
|
|
|
|
|
|
r := require.New(t)
|
|
|
|
a := assert.New(t)
|
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
serv := theBots[0].Server
|
|
|
|
botA := theBots[1].Server
|
|
|
|
botB := theBots[2].Server
|
2021-01-26 17:33:29 +00:00
|
|
|
|
2021-03-19 10:51:06 +00:00
|
|
|
// allow both clients
|
2021-03-29 08:23:03 +00:00
|
|
|
theBots[0].Members.Add(ctx, botA.Whoami(), roomdb.RoleMember)
|
|
|
|
theBots[0].Members.Add(ctx, botB.Whoami(), roomdb.RoleMember)
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
// allow bots to dial the remote
|
2021-03-29 08:23:03 +00:00
|
|
|
theBots[1].Members.Add(ctx, serv.Whoami(), roomdb.RoleMember)
|
|
|
|
theBots[2].Members.Add(ctx, serv.Whoami(), roomdb.RoleMember)
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
// should work (we allowed A)
|
|
|
|
err := botA.Network.Connect(ctx, serv.Network.GetListenAddr())
|
|
|
|
r.NoError(err, "connect A to the Server")
|
|
|
|
|
|
|
|
// shouldn't work (we did not allowed A)
|
|
|
|
err = botB.Network.Connect(ctx, serv.Network.GetListenAddr())
|
|
|
|
r.NoError(err, "connect B to the Server") // we dont see an error because it just establishes the tcp connection
|
|
|
|
|
|
|
|
t.Log("letting handshaking settle..")
|
2021-01-25 15:35:22 +00:00
|
|
|
time.Sleep(1 * time.Second)
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
var srvWho struct {
|
|
|
|
ID refs.FeedRef
|
2021-01-25 15:35:22 +00:00
|
|
|
}
|
2021-01-26 17:33:29 +00:00
|
|
|
edpOfA, has := botA.Network.GetEndpointFor(serv.Whoami())
|
|
|
|
r.True(has, "botA has no endpoint for the server")
|
|
|
|
|
|
|
|
edpOfB, has := botB.Network.GetEndpointFor(serv.Whoami())
|
|
|
|
r.True(has, "botB has no endpoint for the server!")
|
|
|
|
|
|
|
|
err = edpOfA.Async(ctx, &srvWho, muxrpc.TypeJSON, muxrpc.Method{"whoami"})
|
|
|
|
r.NoError(err)
|
|
|
|
a.True(serv.Whoami().Equal(&srvWho.ID))
|
|
|
|
|
|
|
|
err = edpOfB.Async(ctx, &srvWho, muxrpc.TypeJSON, muxrpc.Method{"whoami"})
|
|
|
|
r.NoError(err)
|
|
|
|
a.True(serv.Whoami().Equal(&srvWho.ID))
|
|
|
|
|
|
|
|
// let B listen for changes
|
|
|
|
newRoomMember, err := edpOfB.Source(ctx, muxrpc.TypeJSON, muxrpc.Method{"tunnel", "endpoints"})
|
|
|
|
r.NoError(err)
|
|
|
|
|
|
|
|
newMemberChan := make(chan string)
|
|
|
|
|
|
|
|
// read all the messages from endpoints and throw them over the channel
|
|
|
|
go func() {
|
|
|
|
for newRoomMember.Next(ctx) {
|
|
|
|
|
|
|
|
body, err := newRoomMember.Bytes()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
newMemberChan <- string(body)
|
|
|
|
}
|
|
|
|
close(newMemberChan)
|
|
|
|
}()
|
|
|
|
|
|
|
|
// announce A
|
2021-01-27 10:41:08 +00:00
|
|
|
var ret bool
|
2021-01-26 17:33:29 +00:00
|
|
|
err = edpOfA.Async(ctx, &ret, muxrpc.TypeJSON, muxrpc.Method{"tunnel", "announce"})
|
|
|
|
r.NoError(err)
|
2021-01-27 10:41:08 +00:00
|
|
|
a.False(ret) // <ascii-shrugg>
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(10 * time.Second):
|
|
|
|
t.Error("timeout")
|
|
|
|
case got := <-newMemberChan:
|
|
|
|
t.Log("received join?")
|
|
|
|
t.Log(got)
|
|
|
|
}
|
|
|
|
time.Sleep(5 * time.Second)
|
|
|
|
|
|
|
|
err = edpOfA.Async(ctx, &ret, muxrpc.TypeJSON, muxrpc.Method{"tunnel", "leave"})
|
|
|
|
r.NoError(err)
|
2021-01-27 10:41:08 +00:00
|
|
|
a.False(ret) // <ascii-shrugg>
|
2021-01-26 17:33:29 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(10 * time.Second):
|
|
|
|
t.Error("timeout")
|
|
|
|
case got := <-newMemberChan:
|
|
|
|
t.Log("received leave?")
|
|
|
|
t.Log(got)
|
|
|
|
}
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
cancel()
|
2021-01-25 12:23:03 +00:00
|
|
|
}
|