reflector.go/reflector/server_test.go
Alex Grintsvayg 65df7bc627 make CI happy
2018-08-15 21:19:38 -04:00

251 lines
4.9 KiB
Go

package reflector
import (
"crypto/rand"
"io"
"strconv"
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/lbryio/reflector.go/store"
"encoding/json"
"sort"
"github.com/lbryio/reflector.go/dht/bits"
"github.com/phayes/freeport"
)
func startServerOnRandomPort(t *testing.T) (*Server, int) {
port, err := freeport.GetFreePort()
if err != nil {
t.Fatal(err)
}
srv := NewServer(&store.MemoryBlobStore{})
err = srv.Start("127.0.0.1:" + strconv.Itoa(port))
if err != nil {
t.Fatal(err)
}
return srv, port
}
func TestClient_NotConnected(t *testing.T) {
c := Client{}
err := c.SendBlob([]byte{})
if err == nil {
t.Error("client should error if it is not connected")
}
}
func TestClient_EmptyBlob(t *testing.T) {
srv, port := startServerOnRandomPort(t)
defer srv.Shutdown()
c := Client{}
err := c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
err = c.SendBlob([]byte{})
if err == nil {
t.Error("client should not send empty blob")
}
}
func TestServer_MediumBlob(t *testing.T) {
srv, port := startServerOnRandomPort(t)
defer srv.Shutdown()
c := Client{}
err := c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
blob := randBlob(1000)
err = c.SendBlob(blob)
if err != nil {
t.Error(err)
}
}
func TestServer_FullBlob(t *testing.T) {
srv, port := startServerOnRandomPort(t)
defer srv.Shutdown()
c := Client{}
err := c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
blob := randBlob(maxBlobSize)
err = c.SendBlob(blob)
if err != nil {
t.Error(err)
}
}
func TestServer_TooBigBlob(t *testing.T) {
srv, port := startServerOnRandomPort(t)
defer srv.Shutdown()
c := Client{}
err := c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
blob := randBlob(maxBlobSize + 1)
err = c.SendBlob(blob)
if err == nil {
t.Error("server should reject blob above max size")
}
}
func TestServer_Timeout(t *testing.T) {
t.Skip("server and client have no way to detect errors right now")
testTimeout := 50 * time.Millisecond
port, err := freeport.GetFreePort()
if err != nil {
t.Fatal(err)
}
srv := NewServer(&store.MemoryBlobStore{})
srv.Timeout = testTimeout
err = srv.Start("127.0.0.1:" + strconv.Itoa(port))
if err != nil {
t.Fatal(err)
}
defer srv.Shutdown()
c := Client{}
err = c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
time.Sleep(testTimeout * 2)
blob := randBlob(10)
err = c.SendBlob(blob)
t.Log(spew.Sdump(err))
if err != io.EOF {
t.Error("server should have timed out by now")
}
}
type mockPartialStore struct {
store.MemoryBlobStore
missing []string
}
func (m mockPartialStore) MissingBlobsForKnownStream(hash string) ([]string, error) {
return m.missing, nil
}
func TestServer_PartialUpload(t *testing.T) {
port, err := freeport.GetFreePort()
if err != nil {
t.Fatal(err)
}
sdHash := bits.Rand().String()
missing := make([]string, 4)
for i := range missing {
missing[i] = bits.Rand().String()
}
st := store.BlobStore(&mockPartialStore{missing: missing})
if _, ok := st.(neededBlobChecker); !ok {
t.Fatal("mock does not implement the relevant interface")
}
err = st.Put(sdHash, randBlob(10))
if err != nil {
t.Fatal(err)
}
srv := NewServer(st)
err = srv.Start("127.0.0.1:" + strconv.Itoa(port))
if err != nil {
t.Fatal(err)
}
defer srv.Shutdown()
c := Client{}
err = c.Connect(":" + strconv.Itoa(port))
if err != nil {
t.Fatal("error connecting client to server", err)
}
sendRequest, err := json.Marshal(sendBlobRequest{
SdBlobHash: sdHash,
SdBlobSize: len(sdHash),
})
if err != nil {
t.Fatal(err)
}
_, err = c.conn.Write(sendRequest)
if err != nil {
t.Fatal(err)
}
var sendResp sendSdBlobResponse
err = json.NewDecoder(c.conn).Decode(&sendResp)
if err != nil {
t.Fatal(err)
}
if sendResp.SendSdBlob {
t.Errorf("expected SendSdBlob = false, got true")
}
if len(sendResp.NeededBlobs) != len(missing) {
t.Fatalf("got %d needed blobs, expected %d", len(sendResp.NeededBlobs), len(missing))
}
sort.Strings(sendResp.NeededBlobs)
sort.Strings(missing)
for i := range missing {
if missing[i] != sendResp.NeededBlobs[i] {
t.Errorf("needed blobs mismatch: %s != %s", missing[i], sendResp.NeededBlobs[i])
}
}
}
//func MakeRandStream(size int) ([]byte, [][]byte) {
// blobs := make([][]byte, int(math.Ceil(float64(size)/maxBlobSize)))
// for i := 0; i < len(blobs); i++ {
// blobs[i] = randBlob(int(math.Min(maxBlobSize, float64(size))))
// size -= maxBlobSize
// }
//
// //TODO: create SD blob for the stream
//
// return nil, blobs
//}
func randBlob(size int) []byte {
//if size > maxBlobSize {
// panic("blob size too big")
//}
blob := make([]byte, size)
_, err := rand.Read(blob)
if err != nil {
panic("failed to make random blob")
}
return blob
}