Skip to content

Commit

Permalink
feat: wip: log load test
Browse files Browse the repository at this point in the history
  • Loading branch information
glouvigny authored and aeddi committed Jun 12, 2019
1 parent 9d76c5a commit d37a8de
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 6 deletions.
5 changes: 2 additions & 3 deletions log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ func NewFromEntryHash(services *io.IpfsServices, identity *identityprovider.Iden
})
}

func NewFromJSON(services *io.IpfsServices, identity *identityprovider.Identity, jsonData []byte, logOptions *NewLogOptions, fetchOptions *entry.FetchOptions) (*Log, error) {
func NewFromJSON(services *io.IpfsServices, identity *identityprovider.Identity, jsonLog *JSONLog, logOptions *NewLogOptions, fetchOptions *entry.FetchOptions) (*Log, error) {
if logOptions == nil {
return nil, errmsg.LogOptionsNotDefined
}
Expand All @@ -561,7 +561,6 @@ func NewFromJSON(services *io.IpfsServices, identity *identityprovider.Identity,
}

// TODO: need to verify the entries with 'key'
jsonLog := JSONLog{}

snapshot, err := FromJSON(services, jsonLog, &entry.FetchOptions{
Length: fetchOptions.Length,
Expand All @@ -573,7 +572,7 @@ func NewFromJSON(services *io.IpfsServices, identity *identityprovider.Identity,
}

return NewLog(services, identity, &NewLogOptions{
ID: logOptions.ID,
ID: snapshot.ID,
AccessController: logOptions.AccessController,
Entries: entry.NewOrderedMapFromEntries(snapshot.Values),
SortFn: logOptions.SortFn,
Expand Down
2 changes: 1 addition & 1 deletion log/log_io.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func FromEntryHash(services *io.IpfsServices, hashes []cid.Cid, options *FetchOp
return sliced, nil
}

func FromJSON(services *io.IpfsServices, jsonLog JSONLog, options *entry.FetchOptions) (*Snapshot, error) {
func FromJSON(services *io.IpfsServices, jsonLog *JSONLog, options *entry.FetchOptions) (*Snapshot, error) {
if services == nil {
return nil, errmsg.IPFSNotDefined
}
Expand Down
6 changes: 6 additions & 0 deletions log/sorting.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ func First (a, b *entry.Entry) (int, error) {
return 1, nil
}

func FirstWriteWins(a, b *entry.Entry) (int, error) {
res, err := LastWriteWins(a, b)

return res * -1, err
}

func LastWriteWins(a, b *entry.Entry) (int, error) {
sortByID := func(a *entry.Entry, b *entry.Entry) (int, error) {
return SortByClockId(a, b, First)
Expand Down
144 changes: 144 additions & 0 deletions test/log_load_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package test

import (
"context"
"fmt"
"github.com/berty/go-ipfs-log/entry"
idp "github.com/berty/go-ipfs-log/identityprovider"
"github.com/berty/go-ipfs-log/io"
ks "github.com/berty/go-ipfs-log/keystore"
"github.com/berty/go-ipfs-log/log"
"github.com/berty/go-ipfs-log/test/logcreator"
dssync "github.com/ipfs/go-datastore/sync"
"testing"
"time"

. "github.com/smartystreets/goconvey/convey"
)

//const BadComparatorReturnsZero = (a, b) => 0

func TestLogLoad(t *testing.T) {
_, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

ipfs := io.NewMemoryServices()

datastore := dssync.MutexWrap(NewIdentityDataStore())
keystore, err := ks.NewKeystore(datastore)
if err != nil {
panic(err)
}

var identities [4]*idp.Identity

for i, char := range []rune{'C', 'B', 'D', 'A'} {
identity, err := idp.CreateIdentity(&idp.CreateIdentityOptions{
Keystore: keystore,
ID: fmt.Sprintf("user%c", char),
Type: "orbitdb",
})

if err != nil {
panic(err)
}

identities[i] = identity
}

firstWriteExpectedData := []string{
"entryA6", "entryA7", "entryA8", "entryA9",
"entryA10", "entryB1", "entryB2", "entryB3",
"entryB4", "entryB5", "entryA1", "entryA2",
"entryA3", "entryA4", "entryA5", "entryC0",
}

Convey("Log - Load", t, FailureHalts, func(c C) {
c.Convey("fromJSON", FailureHalts, func(c C) {
c.Convey("creates a log from an entry", FailureHalts, func(c C) {
fixture, err := logcreator.CreateLogWithSixteenEntries(ipfs, identities)
c.So(err, ShouldBeNil)

data := fixture.Log
json := fixture.JSON

// TODO: Is this useless?
//heads := map[string]*entry.Entry{}
//
//for _, h := range json.Heads {
// e, err := entry.FromMultihash(ipfs, h, identities[0].Provider)
// c.So(err, ShouldBeNil)
//
// heads[e.Hash.String()] = e
//}

l, err := log.NewFromJSON(ipfs, identities[0], json, &log.NewLogOptions{ID: "X"}, &entry.FetchOptions{})
c.So(err, ShouldBeNil)

values := l.Values()

c.So(l.ID, ShouldEqual, data.Heads().At(0).LogID)
c.So(values.Len(), ShouldEqual, 16)
var foundEntries []string
for _, k := range values.Keys() {
foundEntries = append(foundEntries, string(values.UnsafeGet(k).Payload))
}

c.So(foundEntries, ShouldResemble, fixture.ExpectedData)
})

c.Convey("creates a log from an entry with custom tiebreaker", FailureHalts, func(c C) {
fixture, err := logcreator.CreateLogWithSixteenEntries(ipfs, identities)
c.So(err, ShouldBeNil)

data := fixture.Log
json := fixture.JSON

println("")
l, err := log.NewFromJSON(ipfs, identities[0], json, &log.NewLogOptions{ID: "X", SortFn: log.FirstWriteWins}, &entry.FetchOptions{Length: intPtr(-1)})
c.So(err, ShouldBeNil)

values := l.Values()

c.So(l.ID, ShouldEqual, data.Heads().At(0).LogID)
c.So(values.Len(), ShouldEqual, 16)
var foundEntries []string
for _, k := range values.Keys() {
foundEntries = append(foundEntries, string(values.UnsafeGet(k).Payload))
}

// TODO: found out why firstWriteExpectedData is what it is in JS test
c.So(foundEntries, ShouldResemble, firstWriteExpectedData)
_ = firstWriteExpectedData
})
})

c.Convey("fromEntryHash", FailureHalts, func(c C) {
c.Convey("creates a log from an entry hash", FailureHalts, func(c C) {
fixture, err := logcreator.CreateLogWithSixteenEntries(ipfs, identities)
c.So(err, ShouldBeNil)

data := fixture.Log
json := fixture.JSON

log1, err := log.NewFromEntryHash(ipfs, identities[0], json.Heads[0], &log.NewLogOptions{ ID: "X" }, &log.FetchOptions{})
log2, err := log.NewFromEntryHash(ipfs, identities[0], json.Heads[1], &log.NewLogOptions{ ID: "X" }, &log.FetchOptions{})

_, err = log1.Join(log2, -1)
c.So(err, ShouldBeNil)

values := log1.Values()

c.So(log1.ID, ShouldEqual, data.Heads().At(0).LogID)
c.So(values.Len(), ShouldEqual, 16)

var foundEntries []string
for _, k := range values.Keys() {
foundEntries = append(foundEntries, string(values.UnsafeGet(k).Payload))
}

c.So(foundEntries, ShouldResemble, fixture.ExpectedData)
})
})
})
}
153 changes: 153 additions & 0 deletions test/logcreator/logcreator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package logcreator

import (
"fmt"
idp "github.com/berty/go-ipfs-log/identityprovider"
"github.com/berty/go-ipfs-log/io"
"github.com/berty/go-ipfs-log/log"
)

type CreatedLog struct {
Log *log.Log
ExpectedData []string
JSON *log.JSONLog
}

func createLogsFor16Entries(ipfs *io.IpfsServices, identities [4]*idp.Identity) (*log.Log, error) {
logA, err := log.NewLog(ipfs, identities[0], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, err
}

logB, err := log.NewLog(ipfs, identities[1], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, err
}

log3, err := log.NewLog(ipfs, identities[2], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, err
}

l, err := log.NewLog(ipfs, identities[3], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, err
}

for i := 1; i <= 5; i++ {
_, err := logA.Append([]byte(fmt.Sprintf("entryA%d", i)), 1)
if err != nil {
return nil, err
}
}

for i := 1; i <= 5; i++ {
_, err := logB.Append([]byte(fmt.Sprintf("entryB%d", i)), 1)
if err != nil {
return nil, err
}
}

_, err = log3.Join(logA, -1)
if err != nil {
return nil, err
}

_, err = log3.Join(logB, -1)
if err != nil {
return nil, err
}

for i := 6; i <= 10; i++ {
_, err := logA.Append([]byte(fmt.Sprintf("entryA%d", i)), 1)
if err != nil {
return nil, err
}
}

_, err = l.Join(log3, -1)
if err != nil {
return nil, err
}

_, err = l.Append([]byte("entryC0"), 1)
if err != nil {
return nil, err
}

_, err = l.Join(logA, -1)
if err != nil {
return nil, err
}

return l, nil
}

func CreateLogWithSixteenEntries(ipfs *io.IpfsServices, identities [4]*idp.Identity) (*CreatedLog, error) {
expectedData := []string{
"entryA1", "entryB1", "entryA2", "entryB2", "entryA3", "entryB3",
"entryA4", "entryB4", "entryA5", "entryB5",
"entryA6",
"entryC0",
"entryA7", "entryA8", "entryA9", "entryA10",
}

l, err := createLogsFor16Entries(ipfs, identities)
if err != nil {
return nil, err
}

return &CreatedLog{Log: l, ExpectedData: expectedData, JSON: l.ToJSON()}, nil
}

func createLogWithHundredEntries(ipfs *io.IpfsServices, identities [4]*idp.Identity) (*log.Log, []string, error) {
var expectedData []string
const amount = 100

logA, err := log.NewLog(ipfs, identities[0], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, nil, err
}

logB, err := log.NewLog(ipfs, identities[1], &log.NewLogOptions{ID: "X"})
if err != nil {
return nil, nil, err
}

for i := 1; i <= amount; i++ {
entryNameA := fmt.Sprintf("entryA%d", i)
entryNameB := fmt.Sprintf("entryB%d", i)

_, err := logA.Append([]byte(entryNameA), 1)
if err != nil {
return nil, nil, err
}
_, err = logB.Join(logA, -1)
if err != nil {
return nil, nil, err
}

_, err = logB.Append([]byte(entryNameB), 1)
if err != nil {
return nil, nil, err
}

_, err = logA.Join(logB, -1)
if err != nil {
return nil, nil, err
}

expectedData = append(expectedData, entryNameA, entryNameB)
}

return logA, expectedData, nil
}

func CreateLogWithHundredEntries(ipfs *io.IpfsServices, identities [4]*idp.Identity) (*CreatedLog, error) {
l, expectedData, err := createLogWithHundredEntries(ipfs, identities)
if err != nil {
return nil, err
}

return &CreatedLog{Log: l, ExpectedData: expectedData}, nil
}
4 changes: 2 additions & 2 deletions test/signed_log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (t *TestACL) CanAppend(e *entry.Entry, i *idp.Identity) error {
return nil
}

func TestLogCRDT(t *testing.T) {
func TestSignedLog(t *testing.T) {
_, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

Expand Down Expand Up @@ -74,7 +74,7 @@ func TestLogCRDT(t *testing.T) {
identities[i] = identity
}

Convey("creates a signed log", t, FailureHalts, func(c C) {
Convey("Signed Log", t, FailureHalts, func(c C) {
c.Convey("creates a signed log", FailureHalts, func(c C) {
logID := "A"
l, err := log.NewLog(ipfs, identities[0], &log.NewLogOptions{ID: logID})
Expand Down

0 comments on commit d37a8de

Please sign in to comment.