package channeldb import ( "net" "testing" "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) var ( addr1 = &net.TCPAddr{IP: (net.IP)([]byte{0x1}), Port: 1} addr2 = &net.TCPAddr{IP: (net.IP)([]byte{0x2}), Port: 2} addr3 = &net.TCPAddr{IP: (net.IP)([]byte{0x3}), Port: 3} ) // TestMultiAddrSource tests that the multiAddrSource correctly merges and // deduplicates the results of a set of AddrSource implementations. func TestMultiAddrSource(t *testing.T) { t.Parallel() var pk1 = newTestPubKey(t) t.Run("both sources have results", func(t *testing.T) { t.Parallel() var ( src1 = newMockAddrSource(t) src2 = newMockAddrSource(t) ) t.Cleanup(func() { src1.AssertExpectations(t) src2.AssertExpectations(t) }) // Let source 1 know of 2 addresses (addr 1 and 2) for node 1. src1.On("AddrsForNode", pk1).Return( true, []net.Addr{addr1, addr2}, nil, ).Once() // Let source 2 know of 2 addresses (addr 2 and 3) for node 1. src2.On("AddrsForNode", pk1).Return( true, []net.Addr{addr2, addr3}, nil, []net.Addr{addr2, addr3}, nil, ).Once() // Create a multi-addr source that consists of both source 1 // and 2. multiSrc := NewMultiAddrSource(src1, src2) // Query it for the addresses known for node 1. The results // should contain addr 1, 2 and 3. known, addrs, err := multiSrc.AddrsForNode(pk1) require.NoError(t, err) require.True(t, known) require.ElementsMatch(t, addrs, []net.Addr{addr1, addr2, addr3}) }) t.Run("only once source has results", func(t *testing.T) { t.Parallel() var ( src1 = newMockAddrSource(t) src2 = newMockAddrSource(t) ) t.Cleanup(func() { src1.AssertExpectations(t) src2.AssertExpectations(t) }) // Let source 1 know of address 1 for node 1. src1.On("AddrsForNode", pk1).Return( true, []net.Addr{addr1}, nil, ).Once() src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once() // Create a multi-addr source that consists of both source 1 // and 2. multiSrc := NewMultiAddrSource(src1, src2) // Query it for the addresses known for node 1. The results // should contain addr 1. known, addrs, err := multiSrc.AddrsForNode(pk1) require.NoError(t, err) require.True(t, known) require.ElementsMatch(t, addrs, []net.Addr{addr1}) }) t.Run("unknown address", func(t *testing.T) { t.Parallel() var ( src1 = newMockAddrSource(t) src2 = newMockAddrSource(t) ) t.Cleanup(func() { src1.AssertExpectations(t) src2.AssertExpectations(t) }) // Create a multi-addr source that consists of both source 1 // and 2. Neither source known of node 1. multiSrc := NewMultiAddrSource(src1, src2) src1.On("AddrsForNode", pk1).Return(false, nil, nil).Once() src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once() // Query it for the addresses known for node 1. It should return // false to indicate that the node is unknown to all backing // sources. known, addrs, err := multiSrc.AddrsForNode(pk1) require.NoError(t, err) require.False(t, known) require.Empty(t, addrs) }) } type mockAddrSource struct { t *testing.T mock.Mock } var _ AddrSource = (*mockAddrSource)(nil) func newMockAddrSource(t *testing.T) *mockAddrSource { return &mockAddrSource{t: t} } func (m *mockAddrSource) AddrsForNode(pub *btcec.PublicKey) (bool, []net.Addr, error) { args := m.Called(pub) if args.Get(1) == nil { return args.Bool(0), nil, args.Error(2) } addrs, ok := args.Get(1).([]net.Addr) require.True(m.t, ok) return args.Bool(0), addrs, args.Error(2) } func newTestPubKey(t *testing.T) *btcec.PublicKey { priv, err := btcec.NewPrivateKey() require.NoError(t, err) return priv.PubKey() }