lnd/lnwire/reply_channel_range_test.go
Bastien Teinturier 17200afc57
lnwire: explicitly handle empty list when encoding short chan IDs
Before this commit, both writing and reading an encoded empty set of
short channel IDs from the wire would fail. Prior to this commit, we
treated decoding an empty set as a caller error, and failed to write out
the zlib encoding of an empty set in a way that us and the other
implementations were able to read.

To fix this, rather than giving zlib an empty buffer to write out (which
results in an encoding with the zlib header data and the rest), we just
write a blank slice. When decoding, if we have an empty query body, then
we'll return a `nil` slice.

With the above changes, we'll now always write out an empty short
channel ID set as:
```
0001 (1 byte follows) || <encoding_type>
```

A new test has also been added to exercise this case for both known
encoding types.
2020-01-13 20:26:55 -08:00

108 lines
2.7 KiB
Go

package lnwire
import (
"bytes"
"encoding/hex"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
)
// TestReplyChannelRangeUnsorted tests that decoding a ReplyChannelRange request
// that contains duplicate or unsorted ids returns an ErrUnsortedSIDs failure.
func TestReplyChannelRangeUnsorted(t *testing.T) {
for _, test := range unsortedSidTests {
test := test
t.Run(test.name, func(t *testing.T) {
req := &ReplyChannelRange{
EncodingType: test.encType,
ShortChanIDs: test.sids,
noSort: true,
}
var b bytes.Buffer
err := req.Encode(&b, 0)
if err != nil {
t.Fatalf("unable to encode req: %v", err)
}
var req2 ReplyChannelRange
err = req2.Decode(bytes.NewReader(b.Bytes()), 0)
if _, ok := err.(ErrUnsortedSIDs); !ok {
t.Fatalf("expected ErrUnsortedSIDs, got: %T",
err)
}
})
}
}
// TestReplyChannelRangeEmpty tests encoding and decoding a ReplyChannelRange
// that doesn't contain any channel results.
func TestReplyChannelRangeEmpty(t *testing.T) {
t.Parallel()
emptyChannelsTests := []struct {
name string
encType ShortChanIDEncoding
encodedHex string
}{
{
name: "empty plain encoding",
encType: EncodingSortedPlain,
encodedHex: "000000000000000000000000000000000000000" +
"00000000000000000000000000000000100000002" +
"01000100",
},
{
name: "empty zlib encoding",
encType: EncodingSortedZlib,
encodedHex: "00000000000000000000000000000000000000" +
"0000000000000000000000000000000001000000" +
"0201000101",
},
}
for _, test := range emptyChannelsTests {
test := test
t.Run(test.name, func(t *testing.T) {
req := ReplyChannelRange{
QueryChannelRange: QueryChannelRange{
FirstBlockHeight: 1,
NumBlocks: 2,
},
Complete: 1,
EncodingType: test.encType,
ShortChanIDs: nil,
}
// First decode the hex string in the test case into a
// new ReplyChannelRange message. It should be
// identical to the one created above.
var req2 ReplyChannelRange
b, _ := hex.DecodeString(test.encodedHex)
err := req2.Decode(bytes.NewReader(b), 0)
if err != nil {
t.Fatalf("unable to decode req: %v", err)
}
if !reflect.DeepEqual(req, req2) {
t.Fatalf("requests don't match: expected %v got %v",
spew.Sdump(req), spew.Sdump(req2))
}
// Next, we go in the reverse direction: encode the
// request created above, and assert that it matches
// the raw byte encoding.
var b2 bytes.Buffer
err = req.Encode(&b2, 0)
if err != nil {
t.Fatalf("unable to encode req: %v", err)
}
if !bytes.Equal(b, b2.Bytes()) {
t.Fatalf("encoded requests don't match: expected %x got %x",
b, b2.Bytes())
}
})
}
}