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

Feature/map #19

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
36 changes: 18 additions & 18 deletions client-instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ import (
)

var (
singleton *dmsg.Client
once sync.Once
clients = struct {
sync.RWMutex
entries map[cipher.PubKey]*dmsg.Client
}{entries: make(map[cipher.PubKey]*dmsg.Client)}

usedPub cipher.PubKey
usedSec cipher.SecKey

errWrongPubKeyUsed error = errors.New("dmsg client already initialized with different pub key")
errWrongSecKeyUsed error = errors.New("dmsg client already initialized with different sec key")
errCreate error = errors.New("dmsg client don't exists and was not created successfully")
)

func getClient(pubKey cipher.PubKey, secKey cipher.SecKey) (*dmsg.Client, error) {
once.Do(func() {
singleton = dmsg.NewClient(pubKey, secKey, disc.NewHTTP(DefaultDiscoveryURL), dmsg.DefaultConfig())
usedPub = pubKey
usedSec = secKey
})
if pubKey != usedPub {
return nil, errWrongPubKeyUsed
//GetClient returns DMSG client instance.
func GetClient(pubKey cipher.PubKey, secKey cipher.SecKey) (*dmsg.Client, error) {
if val, ok := clients.entries[pubKey]; ok {
return val, nil
}
if secKey != usedSec {
return nil, errWrongSecKeyUsed

clients.Lock()
clients.entries[pubKey] = dmsg.NewClient(pubKey, secKey, disc.NewHTTP(DefaultDiscoveryURL), dmsg.DefaultConfig())
clients.Unlock()

if clients.entries[pubKey] != nil {
return clients.entries[pubKey], nil
}
return singleton, nil

return nil, errCreate
}
179 changes: 177 additions & 2 deletions dmsg-http_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package dmsghttp_test

import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"regexp"
"testing"
"time"

"github.com/SkycoinProject/dmsg"
"github.com/SkycoinProject/dmsg/cipher"
Expand All @@ -19,6 +22,98 @@ const (
testPort uint16 = 8081
)

var (
publicKey = "036c4441b76aad343a9073d12f72d024009feabd8a0ccc92d3f88dacc93aafca65"
secretKey = "c483329a1057a578d0f1b93a5bb190a3bebd71c03f19df73dd9852066c22fc7b"
expectedSmallContent = "small content, small content, small content, small content, small content, "
expectedLargeContent = "" // populated at the start of main, not to keep 1000 occurrences here
)

func TestClientsMapNotConcurent(t *testing.T) {
pk, sk := cipher.GenerateKeyPair()
ppk, ssk := cipher.GenerateKeyPair()
pppk, sssk := cipher.GenerateKeyPair()
c, _ := dmsghttp.GetClient(pk, sk)
ca, _ := dmsghttp.GetClient(ppk, ssk)
cb, _ := dmsghttp.GetClient(pk, sk)
cc, _ := dmsghttp.GetClient(pppk, sssk)
cd, _ := dmsghttp.GetClient(ppk, ssk)
ce, _ := dmsghttp.GetClient(pppk, sssk)

fmt.Println("Client 1 and 3 should be equal")
fmt.Println("PK Client 1 : ", c.EntityCommon.LocalPK())
fmt.Println("PK Client 3 : ", cb.EntityCommon.LocalPK())
require.Equal(t, c.EntityCommon.LocalPK(), cb.EntityCommon.LocalPK())
require.Equal(t, c, cb)

fmt.Println("Client 2 and 5 should be equal")
fmt.Println("PK Client 2 : ", ca.EntityCommon.LocalPK())
fmt.Println("PK Client 5 : ", cd.EntityCommon.LocalPK())
require.Equal(t, ca.EntityCommon.LocalPK(), cd.EntityCommon.LocalPK())
require.Equal(t, ca, cd)

fmt.Println("Client 4 and 6 should be equal")
fmt.Println("PK Client 4 : ", cc.EntityCommon.LocalPK())
fmt.Println("PK Client 6 : ", ce.EntityCommon.LocalPK())
require.Equal(t, cc.EntityCommon.LocalPK(), ce.EntityCommon.LocalPK())
require.Equal(t, cc, ce)
}

func TestClientsMapConcurent(t *testing.T) {
pk, sk := cipher.GenerateKeyPair()
ppk, ssk := cipher.GenerateKeyPair()
pppk, sssk := cipher.GenerateKeyPair()

var c, ca, cb, cc, cd, ce *dmsg.Client

go func() {
c, _ = dmsghttp.GetClient(pk, sk)
ca, _ = dmsghttp.GetClient(ppk, ssk)
cb, _ = dmsghttp.GetClient(pk, sk)
cc, _ = dmsghttp.GetClient(pppk, sssk)
cd, _ = dmsghttp.GetClient(ppk, ssk)
ce, _ = dmsghttp.GetClient(pppk, sssk)
}()

go func() {
c, _ = dmsghttp.GetClient(pk, sk)
ca, _ = dmsghttp.GetClient(ppk, ssk)
cb, _ = dmsghttp.GetClient(pk, sk)
cc, _ = dmsghttp.GetClient(pppk, sssk)
cd, _ = dmsghttp.GetClient(ppk, ssk)
ce, _ = dmsghttp.GetClient(pppk, sssk)
}()

go func() {
c, _ = dmsghttp.GetClient(pk, sk)
ca, _ = dmsghttp.GetClient(ppk, ssk)
cb, _ = dmsghttp.GetClient(pk, sk)
cc, _ = dmsghttp.GetClient(pppk, sssk)
cd, _ = dmsghttp.GetClient(ppk, ssk)
ce, _ = dmsghttp.GetClient(pppk, sssk)
}()

time.Sleep(1 * time.Second)

fmt.Println("Client 1 and 3 should be equal")
fmt.Println("PK Client 1 : ", c.EntityCommon.LocalPK())
fmt.Println("PK Client 3 : ", cb.EntityCommon.LocalPK())
require.Equal(t, c.EntityCommon.LocalPK(), cb.EntityCommon.LocalPK())
require.Equal(t, c, cb)

fmt.Println("Client 2 and 5 should be equal")
fmt.Println("PK Client 2 : ", ca.EntityCommon.LocalPK())
fmt.Println("PK Client 5 : ", cd.EntityCommon.LocalPK())
require.Equal(t, ca.EntityCommon.LocalPK(), cd.EntityCommon.LocalPK())
require.Equal(t, ca, cd)

fmt.Println("Client 4 and 6 should be equal")
fmt.Println("PK Client 4 : ", cc.EntityCommon.LocalPK())
fmt.Println("PK Client 6 : ", ce.EntityCommon.LocalPK())
require.Equal(t, cc.EntityCommon.LocalPK(), ce.EntityCommon.LocalPK())
require.Equal(t, cc, ce)
}

func TestDMSGClient(t *testing.T) {
dmsgD := disc.NewMock()
dmsgS, dmsgSErr := createDmsgSrv(t, dmsgD)
Expand Down Expand Up @@ -201,17 +296,97 @@ func TestDMSGClientWithMultipleRoutes(t *testing.T) {
require.Equal(t, "Routes really do Work!", string(respB))
}

func TestEofShowcase(t *testing.T) {
go createDmsgSrvForEofShowcase()
time.Sleep(5 * time.Second)
createDmsgClientForEofShowcase(t)
}

func createDmsgSrv(t *testing.T, dc disc.APIClient) (srv *dmsg.Server, srvErr <-chan error) {
pk, sk, err := cipher.GenerateDeterministicKeyPair([]byte("s"))
require.NoError(t, err)
l, err := nettest.NewLocalListener("tcp")
require.NoError(t, err)
srv, err = dmsg.NewServer(pk, sk, "", l, dc)
srv = dmsg.NewServer(pk, sk, dc)
require.NoError(t, err)
errCh := make(chan error, 1)
go func() {
errCh <- srv.Serve()
errCh <- srv.Serve(l, "")
close(errCh)
}()
return srv, errCh
}

func createDmsgSrvForEofShowcase() {
port := uint16(9091) // use any port you like here, make sure it's referenced in the cmd/client/http-client.go
dmsgD := disc.NewHTTP("http://http://dmsg.discovery.skywire.cc/")
//dmsgD := disc.NewHTTP("http://localhost:9090")

//sPK, sSK := cipher.GenerateKeyPair()

pK := cipher.PubKey{}
sK := cipher.SecKey{}
pK.UnmarshalText([]byte(publicKey))
sK.UnmarshalText([]byte(secretKey))

// note down public key printed out bellow and use the value in cmd/client/http-client.go 'serverPubKey' value
fmt.Printf("Starting http server on public key: %s and port: %v", pK.Hex(), port)

httpS := dmsghttp.Server{
PubKey: pK,
SecKey: sK,
Port: port,
Discovery: dmsgD,
}

// prepare server route handling
mux := http.NewServeMux()
mux.HandleFunc("/small", dmsghttp.SmallRequestHandler)
mux.HandleFunc("/large", dmsghttp.LargeRequestHandler)

// run the server
sErr := make(chan error, 1)
sErr <- httpS.Serve(mux)
close(sErr)
fmt.Println(sErr)
}

func createDmsgClientForEofShowcase(t *testing.T) {
time.Sleep(5 * time.Second)
var b bytes.Buffer
countExpectedLargeContent := 1000 // how many times we expect 'large content, ' phrase to appear in the response
for i := countExpectedLargeContent; i > 0; i-- {
b.WriteString("large content, ")
}
expectedLargeContent = b.String()

//sPK, sSK := cipher.GenerateKeyPair()
disc := disc.NewHTTP("http://http://dmsg.discovery.skywire.cc/")
//disc := disc.NewHTTP("http://localhost:9090")
pK := cipher.PubKey{}
sK := cipher.SecKey{}
pK.UnmarshalText([]byte(publicKey))
sK.UnmarshalText([]byte(secretKey))
client := dmsghttp.DMSGClient(disc, pK, sK)

// this one is returned ok
resp := dmsghttp.MakeRequest("small", client)
if resp != expectedSmallContent {
fmt.Printf("Received small content is not what's expected. Expected %s but received %s\n", expectedSmallContent, resp)
t.Fail()
return
}
fmt.Println("Small content is ok")

// this one fails with following message "Error reading data: http: unexpected EOF reading trailer"
resp = dmsghttp.MakeRequest("large", client)
if resp != expectedLargeContent {
largeContentRegex := regexp.MustCompile("large content,")
matches := largeContentRegex.FindAllStringIndex(resp, -1)
countActual := len(matches) // how many times we received expected phrase,
fmt.Printf("Received large content is not what's expected. Expected %v but received %v 'large content' occurrences\n", countExpectedLargeContent, countActual)
t.Fail()
return
}
fmt.Print("Large content is ok")
}
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ module github.com/SkycoinProject/dmsg-http
go 1.13

require (
github.com/SkycoinProject/dmsg v0.0.0-20200127093622-ba9543931922
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/SkycoinProject/dmsg v0.0.0-20200224064625-1b539081519c
github.com/go-playground/locales v0.13.0 // indirect
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a
)
Loading