storrent/metainfo/metainfo_test.go
2026-01-19 21:13:01 +09:00

142 lines
3.0 KiB
Go

package metainfo
import (
"crypto/sha1"
"testing"
"storrent/bencode"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
info map[string]any
wantName string
wantSize int64
}{
{
name: "single file",
info: map[string]any{
"name": "test.txt",
"piece length": int64(16384),
"pieces": string(make([]byte, 20)),
"length": int64(100),
},
wantName: "test.txt",
wantSize: 100,
},
{
name: "multi file",
info: map[string]any{
"name": "dir",
"piece length": int64(16384),
"pieces": string(make([]byte, 20)),
"files": []any{
map[string]any{"length": int64(100), "path": []any{"a.txt"}},
map[string]any{"length": int64(200), "path": []any{"b.txt"}},
},
},
wantName: "dir",
wantSize: 300,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data, err := bencode.Encode(map[string]any{"info": tt.info})
if err != nil {
t.Fatalf("Encode: %v", err)
}
m, err := ParseBytes(data)
if err != nil {
t.Fatalf("ParseBytes: %v", err)
}
if m.Info.Name != tt.wantName {
t.Errorf("Name: got %s, want %s", m.Info.Name, tt.wantName)
}
if m.Size != tt.wantSize {
t.Errorf("Size: got %d, want %d", m.Size, tt.wantSize)
}
})
}
}
func TestInfoHash(t *testing.T) {
tests := []struct {
name string
raw string
}{
{
name: "basic",
raw: "d6:lengthi1e4:name4:test12:piece lengthi16384e6:pieces20:01234567890123456789e",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
raw := []byte(tt.raw)
torrent := append([]byte("d4:info"), raw...)
torrent = append(torrent, 'e')
m, err := ParseBytes(torrent)
if err != nil {
t.Fatalf("ParseBytes: %v", err)
}
want := sha1.Sum(raw)
if m.InfoHash != want {
t.Errorf("InfoHash: got %x, want %x", m.InfoHash, want)
}
})
}
}
func TestSegments(t *testing.T) {
tests := []struct {
name string
files []Entry
off int64
size int64
want []Segment
}{
{
name: "single file",
files: []Entry{{Size: 32, Offset: 0}},
off: 0,
size: 32,
want: []Segment{{0, 0, 32}},
},
{
name: "spans two files",
files: []Entry{{Size: 16, Offset: 0}, {Size: 16, Offset: 16}},
off: 0,
size: 32,
want: []Segment{{0, 0, 16}, {1, 0, 16}},
},
{
name: "middle of file",
files: []Entry{{Size: 32, Offset: 0}},
off: 8,
size: 16,
want: []Segment{{0, 8, 16}},
},
{
name: "skip first file",
files: []Entry{{Size: 16, Offset: 0}, {Size: 16, Offset: 16}},
off: 16,
size: 16,
want: []Segment{{1, 0, 16}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
info := Info{Files: tt.files}
got := info.Segments(tt.off, tt.size)
if len(got) != len(tt.want) {
t.Fatalf("got %d segments, want %d", len(got), len(tt.want))
}
for i := range got {
if got[i] != tt.want[i] {
t.Errorf("segment %d: got %+v, want %+v", i, got[i], tt.want[i])
}
}
})
}
}