From aff2ecbca071518dda28d1736baea0aedd8b18ec Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Wed, 1 Feb 2023 20:58:20 +0300 Subject: [PATCH 1/8] ldiff: Element by id --- app/ldiff/diff.go | 17 ++++++++++- app/ldiff/diff_test.go | 48 ++++++++++++++++++++++++++++++ app/ldiff/mock_ldiff/mock_ldiff.go | 15 ++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/app/ldiff/diff.go b/app/ldiff/diff.go index bd9ebcf2..dd49d980 100644 --- a/app/ldiff/diff.go +++ b/app/ldiff/diff.go @@ -51,7 +51,7 @@ var hashersPool = &sync.Pool{ }, } -var ErrElementNotFound = errors.New("element not found") +var ErrElementNotFound = errors.New("ldiff: element not found") // Element of data type Element struct { @@ -88,6 +88,8 @@ type Diff interface { Diff(ctx context.Context, dl Remote) (newIds, changedIds, removedIds []string, err error) // Elements retrieves all elements in the Diff Elements() []Element + // Element returns an element by id + Element(id string) (Element, error) // Ids retrieves ids of all elements in the Diff Ids() []string // Hash returns hash of all elements in the diff @@ -172,6 +174,19 @@ func (d *diff) Elements() (elements []Element) { return } +func (d *diff) Element(id string) (Element, error) { + d.mu.RLock() + defer d.mu.RUnlock() + el := d.sl.Get(&element{Element: Element{Id: id}, hash: xxhash.Sum64([]byte(id))}) + if el == nil { + return Element{}, ErrElementNotFound + } + if e, ok := el.Key().(*element); ok { + return e.Element, nil + } + return Element{}, ErrElementNotFound +} + func (d *diff) Hash() string { d.mu.RLock() defer d.mu.RUnlock() diff --git a/app/ldiff/diff_test.go b/app/ldiff/diff_test.go index 8d8db28d..682bf1d5 100644 --- a/app/ldiff/diff_test.go +++ b/app/ldiff/diff_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/mgo.v2/bson" "math" + "sort" "testing" ) @@ -148,3 +149,50 @@ func TestDiff_Hash(t *testing.T) { assert.NotEmpty(t, h2) assert.NotEqual(t, h1, h2) } + +func TestDiff_Element(t *testing.T) { + d := New(16, 16) + for i := 0; i < 10; i++ { + d.Set(Element{Id: fmt.Sprint("id", i), Head: fmt.Sprint("head", i)}) + } + _, err := d.Element("not found") + assert.Equal(t, ErrElementNotFound, err) + + el, err := d.Element("id5") + require.NoError(t, err) + assert.Equal(t, "head5", el.Head) + + d.Set(Element{"id5", "otherHead"}) + el, err = d.Element("id5") + require.NoError(t, err) + assert.Equal(t, "otherHead", el.Head) +} + +func TestDiff_Ids(t *testing.T) { + d := New(16, 16) + var ids []string + for i := 0; i < 10; i++ { + id := fmt.Sprint("id", i) + d.Set(Element{Id: id, Head: fmt.Sprint("head", i)}) + ids = append(ids, id) + } + gotIds := d.Ids() + sort.Strings(gotIds) + assert.Equal(t, ids, gotIds) +} + +func TestDiff_Elements(t *testing.T) { + d := New(16, 16) + var els []Element + for i := 0; i < 10; i++ { + id := fmt.Sprint("id", i) + el := Element{Id: id, Head: fmt.Sprint("head", i)} + d.Set(el) + els = append(els, el) + } + gotEls := d.Elements() + sort.Slice(gotEls, func(i, j int) bool { + return gotEls[i].Id < gotEls[j].Id + }) + assert.Equal(t, els, gotEls) +} diff --git a/app/ldiff/mock_ldiff/mock_ldiff.go b/app/ldiff/mock_ldiff/mock_ldiff.go index 119d7042..328956fa 100644 --- a/app/ldiff/mock_ldiff/mock_ldiff.go +++ b/app/ldiff/mock_ldiff/mock_ldiff.go @@ -52,6 +52,21 @@ func (mr *MockDiffMockRecorder) Diff(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Diff", reflect.TypeOf((*MockDiff)(nil).Diff), arg0, arg1) } +// Element mocks base method. +func (m *MockDiff) Element(arg0 string) (ldiff.Element, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Element", arg0) + ret0, _ := ret[0].(ldiff.Element) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Element indicates an expected call of Element. +func (mr *MockDiffMockRecorder) Element(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Element", reflect.TypeOf((*MockDiff)(nil).Element), arg0) +} + // Elements mocks base method. func (m *MockDiff) Elements() []ldiff.Element { m.ctrl.T.Helper() From f4c6679b0e3d72a71b2ca42749471d2ec7e593c0 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Wed, 1 Feb 2023 21:38:47 +0300 Subject: [PATCH 2/8] ldiff: Len --- app/ldiff/diff.go | 8 ++++++++ app/ldiff/diff_test.go | 1 + 2 files changed, 9 insertions(+) diff --git a/app/ldiff/diff.go b/app/ldiff/diff.go index dd49d980..f0a2f197 100644 --- a/app/ldiff/diff.go +++ b/app/ldiff/diff.go @@ -94,6 +94,8 @@ type Diff interface { Ids() []string // Hash returns hash of all elements in the diff Hash() string + // Len returns count of elements in the diff + Len() int } // Remote interface for using in the Diff @@ -159,6 +161,12 @@ func (d *diff) Ids() (ids []string) { return } +func (d *diff) Len() int { + d.mu.RLock() + defer d.mu.RUnlock() + return d.sl.Len() +} + func (d *diff) Elements() (elements []Element) { d.mu.RLock() defer d.mu.RUnlock() diff --git a/app/ldiff/diff_test.go b/app/ldiff/diff_test.go index 682bf1d5..e15f6b82 100644 --- a/app/ldiff/diff_test.go +++ b/app/ldiff/diff_test.go @@ -179,6 +179,7 @@ func TestDiff_Ids(t *testing.T) { gotIds := d.Ids() sort.Strings(gotIds) assert.Equal(t, ids, gotIds) + assert.Equal(t, len(ids), d.Len()) } func TestDiff_Elements(t *testing.T) { From 3fcbe3aba9104cec0eacb1fc9cda873f54c2254d Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 2 Feb 2023 13:12:52 +0300 Subject: [PATCH 3/8] testPool: implement pool.Service --- net/rpc/rpctest/pool.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/rpc/rpctest/pool.go b/net/rpc/rpctest/pool.go index 1b28fa56..e7d0893d 100644 --- a/net/rpc/rpctest/pool.go +++ b/net/rpc/rpctest/pool.go @@ -66,6 +66,10 @@ func (t *TestPool) DialOneOf(ctx context.Context, peerIds []string) (peer.Peer, return &testPeer{id: peerIds[rand.Intn(len(peerIds))], Conn: t.ts.Dial(ctx)}, nil } +func (t *TestPool) NewPool(name string) pool.Pool { + return t +} + func (t *TestPool) Init(a *app.App) (err error) { return nil } From 6d2178dfc95d29908dc31bf0932ce7841bc568cf Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 2 Feb 2023 13:18:30 +0300 Subject: [PATCH 4/8] testPool: add peers --- net/rpc/rpctest/pool.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/net/rpc/rpctest/pool.go b/net/rpc/rpctest/pool.go index e7d0893d..5faedd44 100644 --- a/net/rpc/rpctest/pool.go +++ b/net/rpc/rpctest/pool.go @@ -15,12 +15,15 @@ import ( var ErrCantConnect = errors.New("can't connect to test server") func NewTestPool() *TestPool { - return &TestPool{} + return &TestPool{ + peers: map[string]peer.Peer{}, + } } type TestPool struct { - ts *TesServer - mu sync.Mutex + ts *TesServer + peers map[string]peer.Peer + mu sync.Mutex } func (t *TestPool) WithServer(ts *TesServer) *TestPool { @@ -33,6 +36,9 @@ func (t *TestPool) WithServer(ts *TesServer) *TestPool { func (t *TestPool) Get(ctx context.Context, id string) (peer.Peer, error) { t.mu.Lock() defer t.mu.Unlock() + if p, ok := t.peers[id]; ok { + return p, nil + } if t.ts == nil { return nil, ErrCantConnect } @@ -51,6 +57,11 @@ func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) { func (t *TestPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { t.mu.Lock() defer t.mu.Unlock() + for _, peerId := range peerIds { + if p, ok := t.peers[peerId]; ok { + return p, nil + } + } if t.ts == nil { return nil, ErrCantConnect } @@ -70,6 +81,12 @@ func (t *TestPool) NewPool(name string) pool.Pool { return t } +func (t *TestPool) AddPeer(p peer.Peer) { + t.mu.Lock() + defer t.mu.Unlock() + t.peers[p.Id()] = p +} + func (t *TestPool) Init(a *app.App) (err error) { return nil } From d2a19d21fecd6369569493286eaa83931a654e1a Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 2 Feb 2023 13:19:20 +0300 Subject: [PATCH 5/8] fix ldiff mock --- app/ldiff/mock_ldiff/mock_ldiff.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/ldiff/mock_ldiff/mock_ldiff.go b/app/ldiff/mock_ldiff/mock_ldiff.go index 328956fa..5aa89825 100644 --- a/app/ldiff/mock_ldiff/mock_ldiff.go +++ b/app/ldiff/mock_ldiff/mock_ldiff.go @@ -109,6 +109,20 @@ func (mr *MockDiffMockRecorder) Ids() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ids", reflect.TypeOf((*MockDiff)(nil).Ids)) } +// Len mocks base method. +func (m *MockDiff) Len() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Len") + ret0, _ := ret[0].(int) + return ret0 +} + +// Len indicates an expected call of Len. +func (mr *MockDiffMockRecorder) Len() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Len", reflect.TypeOf((*MockDiff)(nil).Len)) +} + // Ranges mocks base method. func (m *MockDiff) Ranges(arg0 context.Context, arg1 []ldiff.Range, arg2 []ldiff.RangeResult) ([]ldiff.RangeResult, error) { m.ctrl.T.Helper() From 75c660916d90ca257f01122e151fc6f6e1639ce6 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 2 Feb 2023 21:16:59 +0300 Subject: [PATCH 6/8] fix --- net/rpc/rpctest/pool.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/rpc/rpctest/pool.go b/net/rpc/rpctest/pool.go index 5faedd44..4824d421 100644 --- a/net/rpc/rpctest/pool.go +++ b/net/rpc/rpctest/pool.go @@ -48,10 +48,7 @@ func (t *TestPool) Get(ctx context.Context, id string) (peer.Peer, error) { func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) { t.mu.Lock() defer t.mu.Unlock() - if t.ts == nil { - return nil, ErrCantConnect - } - return &testPeer{id: id, Conn: t.ts.Dial(ctx)}, nil + return t.Get(ctx, id) } func (t *TestPool) GetOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) { From cc2a98bbadc3f46a836a8e20e782024a9cf09ea8 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 2 Feb 2023 21:21:25 +0300 Subject: [PATCH 7/8] fix --- net/rpc/rpctest/pool.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/rpc/rpctest/pool.go b/net/rpc/rpctest/pool.go index 4824d421..7fdbdda4 100644 --- a/net/rpc/rpctest/pool.go +++ b/net/rpc/rpctest/pool.go @@ -46,8 +46,6 @@ func (t *TestPool) Get(ctx context.Context, id string) (peer.Peer, error) { } func (t *TestPool) Dial(ctx context.Context, id string) (peer.Peer, error) { - t.mu.Lock() - defer t.mu.Unlock() return t.Get(ctx, id) } From 163c0e4058012f8bdbf723737479ffd55a3a0c4e Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Sat, 4 Feb 2023 15:20:34 +0300 Subject: [PATCH 8/8] testrpc server implement app.Component --- net/rpc/rpctest/server.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net/rpc/rpctest/server.go b/net/rpc/rpctest/server.go index 9a36d288..5efc596a 100644 --- a/net/rpc/rpctest/server.go +++ b/net/rpc/rpctest/server.go @@ -2,6 +2,8 @@ package rpctest import ( "context" + "github.com/anytypeio/any-sync/app" + "github.com/anytypeio/any-sync/net/rpc/server" "net" "storj.io/drpc" "storj.io/drpc/drpcconn" @@ -22,6 +24,22 @@ type TesServer struct { *drpcserver.Server } +func (ts *TesServer) Init(a *app.App) (err error) { + return nil +} + +func (ts *TesServer) Name() (name string) { + return server.CName +} + +func (ts *TesServer) Run(ctx context.Context) (err error) { + return nil +} + +func (ts *TesServer) Close(ctx context.Context) (err error) { + return nil +} + func (ts *TesServer) Dial(ctx context.Context) drpc.Conn { sc, cc := net.Pipe() go ts.Server.ServeOne(ctx, sc)