2018-05-10 14:47:54 +00:00
|
|
|
package shhext
|
|
|
|
|
|
|
|
import (
|
2018-12-14 11:21:34 +00:00
|
|
|
"context"
|
2018-12-11 10:23:47 +00:00
|
|
|
"encoding/hex"
|
2018-05-10 14:47:54 +00:00
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
2019-10-09 14:22:53 +00:00
|
|
|
|
2018-12-11 10:23:47 +00:00
|
|
|
"github.com/status-im/status-go/mailserver"
|
|
|
|
|
2018-10-15 21:15:04 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2018-05-10 14:47:54 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestMessagesRequest_setDefaults(t *testing.T) {
|
|
|
|
daysAgo := func(now time.Time, days int) uint32 {
|
|
|
|
return uint32(now.UTC().Add(-24 * time.Hour * time.Duration(days)).Unix())
|
|
|
|
}
|
|
|
|
|
|
|
|
tnow := time.Now()
|
|
|
|
now := uint32(tnow.UTC().Unix())
|
|
|
|
yesterday := daysAgo(tnow, 1)
|
|
|
|
|
|
|
|
scenarios := []struct {
|
|
|
|
given *MessagesRequest
|
|
|
|
expected *MessagesRequest
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
&MessagesRequest{From: 0, To: 0},
|
2018-06-15 15:12:31 +00:00
|
|
|
&MessagesRequest{From: yesterday, To: now, Timeout: defaultRequestTimeout},
|
2018-05-10 14:47:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
&MessagesRequest{From: 1, To: 0},
|
2018-06-15 15:12:31 +00:00
|
|
|
&MessagesRequest{From: uint32(1), To: now, Timeout: defaultRequestTimeout},
|
2018-05-10 14:47:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
&MessagesRequest{From: 0, To: yesterday},
|
2018-06-15 15:12:31 +00:00
|
|
|
&MessagesRequest{From: daysAgo(tnow, 2), To: yesterday, Timeout: defaultRequestTimeout},
|
2018-05-10 14:47:54 +00:00
|
|
|
},
|
|
|
|
// 100 - 1 day would be invalid, so we set From to 0
|
|
|
|
{
|
|
|
|
&MessagesRequest{From: 0, To: 100},
|
2018-06-15 15:12:31 +00:00
|
|
|
&MessagesRequest{From: 0, To: 100, Timeout: defaultRequestTimeout},
|
|
|
|
},
|
|
|
|
// set Timeout
|
|
|
|
{
|
|
|
|
&MessagesRequest{From: 0, To: 0, Timeout: 100},
|
|
|
|
&MessagesRequest{From: yesterday, To: now, Timeout: 100},
|
2018-05-10 14:47:54 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, s := range scenarios {
|
|
|
|
t.Run(fmt.Sprintf("Scenario %d", i), func(t *testing.T) {
|
|
|
|
s.given.setDefaults(tnow)
|
|
|
|
require.Equal(t, s.expected, s.given)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-10-15 21:15:04 +00:00
|
|
|
|
2018-12-11 10:23:47 +00:00
|
|
|
func TestMakeMessagesRequestPayload(t *testing.T) {
|
2019-11-23 17:57:05 +00:00
|
|
|
var emptyTopic types.TopicType
|
2018-12-11 10:23:47 +00:00
|
|
|
testCases := []struct {
|
|
|
|
Name string
|
|
|
|
Req MessagesRequest
|
|
|
|
Err string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "empty cursor",
|
|
|
|
Req: MessagesRequest{Cursor: ""},
|
|
|
|
Err: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "invalid cursor size",
|
|
|
|
Req: MessagesRequest{Cursor: hex.EncodeToString([]byte{0x01, 0x02, 0x03})},
|
2019-05-09 10:58:02 +00:00
|
|
|
Err: fmt.Sprintf("invalid cursor size: expected %d but got 3", mailserver.CursorLength),
|
2018-12-11 10:23:47 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "valid cursor",
|
|
|
|
Req: MessagesRequest{
|
2019-11-23 17:57:05 +00:00
|
|
|
Cursor: hex.EncodeToString(mailserver.NewDBKey(123, emptyTopic, types.Hash{}).Cursor()),
|
2018-12-11 10:23:47 +00:00
|
|
|
},
|
|
|
|
Err: "",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
_, err := makeMessagesRequestPayload(tc.Req)
|
|
|
|
if tc.Err == "" {
|
|
|
|
require.NoError(t, err)
|
|
|
|
} else {
|
|
|
|
require.EqualError(t, err, tc.Err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-15 21:15:04 +00:00
|
|
|
func TestTopicsToBloom(t *testing.T) {
|
|
|
|
t1 := stringToTopic("t1")
|
2019-11-23 17:57:05 +00:00
|
|
|
b1 := types.TopicToBloom(t1)
|
2018-10-15 21:15:04 +00:00
|
|
|
t2 := stringToTopic("t2")
|
2019-11-23 17:57:05 +00:00
|
|
|
b2 := types.TopicToBloom(t2)
|
2018-10-15 21:15:04 +00:00
|
|
|
t3 := stringToTopic("t3")
|
2019-11-23 17:57:05 +00:00
|
|
|
b3 := types.TopicToBloom(t3)
|
2018-10-15 21:15:04 +00:00
|
|
|
|
|
|
|
reqBloom := topicsToBloom(t1)
|
2019-11-23 17:57:05 +00:00
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b1))
|
|
|
|
assert.False(t, types.BloomFilterMatch(reqBloom, b2))
|
|
|
|
assert.False(t, types.BloomFilterMatch(reqBloom, b3))
|
2018-10-15 21:15:04 +00:00
|
|
|
|
|
|
|
reqBloom = topicsToBloom(t1, t2)
|
2019-11-23 17:57:05 +00:00
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b1))
|
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b2))
|
|
|
|
assert.False(t, types.BloomFilterMatch(reqBloom, b3))
|
2018-10-15 21:15:04 +00:00
|
|
|
|
|
|
|
reqBloom = topicsToBloom(t1, t2, t3)
|
2019-11-23 17:57:05 +00:00
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b1))
|
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b2))
|
|
|
|
assert.True(t, types.BloomFilterMatch(reqBloom, b3))
|
2018-10-15 21:15:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateBloomFilter(t *testing.T) {
|
|
|
|
t1 := stringToTopic("t1")
|
|
|
|
t2 := stringToTopic("t2")
|
|
|
|
|
|
|
|
req := MessagesRequest{Topic: t1}
|
|
|
|
bloom := createBloomFilter(req)
|
|
|
|
assert.Equal(t, topicsToBloom(t1), bloom)
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
req = MessagesRequest{Topics: []types.TopicType{t1, t2}}
|
2018-10-15 21:15:04 +00:00
|
|
|
bloom = createBloomFilter(req)
|
|
|
|
assert.Equal(t, topicsToBloom(t1, t2), bloom)
|
|
|
|
}
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
func stringToTopic(s string) types.TopicType {
|
|
|
|
return types.BytesToTopic([]byte(s))
|
2018-10-15 21:15:04 +00:00
|
|
|
}
|
2018-12-14 11:21:34 +00:00
|
|
|
|
|
|
|
func TestCreateSyncMailRequest(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
Name string
|
|
|
|
Req SyncMessagesRequest
|
2019-11-23 17:57:05 +00:00
|
|
|
Verify func(*testing.T, types.SyncMailRequest)
|
2018-12-14 11:21:34 +00:00
|
|
|
Error string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "no topics",
|
|
|
|
Req: SyncMessagesRequest{},
|
2019-11-23 17:57:05 +00:00
|
|
|
Verify: func(t *testing.T, r types.SyncMailRequest) {
|
|
|
|
require.Equal(t, types.MakeFullNodeBloom(), r.Bloom)
|
2018-12-14 11:21:34 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "some topics",
|
|
|
|
Req: SyncMessagesRequest{
|
2019-11-23 17:57:05 +00:00
|
|
|
Topics: []types.TopicType{{0x01, 0xff, 0xff, 0xff}},
|
2018-12-14 11:21:34 +00:00
|
|
|
},
|
2019-11-23 17:57:05 +00:00
|
|
|
Verify: func(t *testing.T, r types.SyncMailRequest) {
|
|
|
|
expectedBloom := types.TopicToBloom(types.TopicType{0x01, 0xff, 0xff, 0xff})
|
2018-12-14 11:21:34 +00:00
|
|
|
require.Equal(t, expectedBloom, r.Bloom)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "decode cursor",
|
|
|
|
Req: SyncMessagesRequest{
|
|
|
|
Cursor: hex.EncodeToString([]byte{0x01, 0x02, 0x03}),
|
|
|
|
},
|
2019-11-23 17:57:05 +00:00
|
|
|
Verify: func(t *testing.T, r types.SyncMailRequest) {
|
2018-12-14 11:21:34 +00:00
|
|
|
require.Equal(t, []byte{0x01, 0x02, 0x03}, r.Cursor)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
r, err := createSyncMailRequest(tc.Req)
|
|
|
|
if tc.Error != "" {
|
|
|
|
require.EqualError(t, err, tc.Error)
|
|
|
|
}
|
|
|
|
tc.Verify(t, r)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSyncMessagesErrors(t *testing.T) {
|
|
|
|
validEnode := "enode://e8a7c03b58911e98bbd66accb2a55d57683f35b23bf9dfca89e5e244eb5cc3f25018b4112db507faca34fb69ffb44b362f79eda97a669a8df29c72e654416784@127.0.0.1:30404"
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
Name string
|
|
|
|
Req SyncMessagesRequest
|
|
|
|
Resp SyncMessagesResponse
|
|
|
|
Error string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "invalid MailServerPeer",
|
|
|
|
Req: SyncMessagesRequest{MailServerPeer: "invalid-scheme://"},
|
|
|
|
Error: `invalid MailServerPeer: invalid URL scheme, want "enode"`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "failed to create SyncMailRequest",
|
|
|
|
Req: SyncMessagesRequest{
|
|
|
|
MailServerPeer: validEnode,
|
|
|
|
Cursor: "a", // odd number of characters is an invalid hex representation
|
|
|
|
},
|
|
|
|
Error: "failed to create a sync mail request: encoding/hex: odd length hex string",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
api := PublicAPI{}
|
|
|
|
resp, err := api.SyncMessages(context.TODO(), tc.Req)
|
|
|
|
if tc.Error != "" {
|
|
|
|
require.EqualError(t, err, tc.Error)
|
|
|
|
}
|
|
|
|
require.EqualValues(t, tc.Resp, resp)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2019-05-20 08:10:26 +00:00
|
|
|
|
|
|
|
func TestExpiredOrCompleted(t *testing.T) {
|
|
|
|
timeout := time.Millisecond
|
2019-11-23 17:57:05 +00:00
|
|
|
events := make(chan types.EnvelopeEvent)
|
2019-05-20 08:10:26 +00:00
|
|
|
errors := make(chan error, 1)
|
2019-11-23 17:57:05 +00:00
|
|
|
hash := types.Hash{1}
|
2019-05-20 08:10:26 +00:00
|
|
|
go func() {
|
|
|
|
_, err := waitForExpiredOrCompleted(hash, events, timeout)
|
|
|
|
errors <- err
|
|
|
|
}()
|
|
|
|
select {
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
require.FailNow(t, "timed out waiting for waitForExpiredOrCompleted to complete")
|
|
|
|
case err := <-errors:
|
|
|
|
require.EqualError(t, err, fmt.Sprintf("request %x expired", hash))
|
|
|
|
}
|
|
|
|
}
|