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]) } } }) } }