Ztorrent/internal/torrentfile/torrentfile_test.go
2026-03-06 12:52:01 +03:00

155 lines
4.5 KiB
Go

package torrentfile
import (
"crypto/sha1"
"os"
"path/filepath"
"testing"
)
func TestOpenParsesTorrentMetadata(t *testing.T) {
t.Parallel()
info := "d6:lengthi5e4:name8:test.txt12:piece lengthi16384e6:pieces20:aaaaaaaaaaaaaaaaaaaa7:privatei1ee"
torrent := "d8:announce14:http://tracker4:info" + info + "e"
path := writeTempTorrent(t, torrent)
tf, err := Open(path)
if err != nil {
t.Fatalf("Open returned error: %v", err)
}
expectedHash := sha1.Sum([]byte(info))
if tf.InfoHash != expectedHash {
t.Fatalf("unexpected info hash: got %x want %x", tf.InfoHash, expectedHash)
}
if tf.Announce != "http://tracker" {
t.Fatalf("unexpected announce: got %q", tf.Announce)
}
if len(tf.Trackers) != 1 || tf.Trackers[0] != "http://tracker" {
t.Fatalf("unexpected trackers list: %#v", tf.Trackers)
}
if tf.Name != "test.txt" {
t.Fatalf("unexpected name: got %q", tf.Name)
}
if tf.PieceLength != 16384 {
t.Fatalf("unexpected piece length: got %d", tf.PieceLength)
}
if tf.Length != 5 {
t.Fatalf("unexpected length: got %d", tf.Length)
}
if len(tf.PieceHashes) != 1 {
t.Fatalf("unexpected piece count: got %d", len(tf.PieceHashes))
}
if len(tf.Files) != 1 {
t.Fatalf("unexpected file count: got %d", len(tf.Files))
}
if got, want := tf.Files[0].Path, "test.txt"; got != want {
t.Fatalf("unexpected first file path: got %q want %q", got, want)
}
if got, want := tf.Files[0].Length, 5; got != want {
t.Fatalf("unexpected first file length: got %d want %d", got, want)
}
var expectedPiece [20]byte
copy(expectedPiece[:], []byte("aaaaaaaaaaaaaaaaaaaa"))
if tf.PieceHashes[0] != expectedPiece {
t.Fatalf("unexpected piece hash: got %x want %x", tf.PieceHashes[0], expectedPiece)
}
}
func TestOpenRejectsInvalidPieceHashes(t *testing.T) {
t.Parallel()
info := "d6:lengthi5e4:name8:test.txt12:piece lengthi16384e6:pieces19:aaaaaaaaaaaaaaaaaaae"
torrent := "d8:announce14:http://tracker4:info" + info + "e"
path := writeTempTorrent(t, torrent)
_, err := Open(path)
if err == nil {
t.Fatal("expected Open to fail for invalid piece hash length")
}
}
func TestOpenParsesMultiFileTorrent(t *testing.T) {
t.Parallel()
pieces := "aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb"
info := "d5:filesld6:lengthi3e4:pathl5:a.txteed6:lengthi2e4:pathl5:b.txteee4:name4:root12:piece lengthi4e6:pieces40:" + pieces + "e"
torrent := "d8:announce14:http://tracker4:info" + info + "e"
path := writeTempTorrent(t, torrent)
tf, err := Open(path)
if err != nil {
t.Fatalf("Open returned error: %v", err)
}
if tf.Length != 5 {
t.Fatalf("unexpected total length: got %d", tf.Length)
}
if len(tf.Files) != 2 {
t.Fatalf("unexpected file count: got %d", len(tf.Files))
}
if got, want := tf.Files[0].Path, "root/a.txt"; got != want {
t.Fatalf("unexpected file[0] path: got %q want %q", got, want)
}
if got, want := tf.Files[1].Path, "root/b.txt"; got != want {
t.Fatalf("unexpected file[1] path: got %q want %q", got, want)
}
if len(tf.PieceHashes) != 2 {
t.Fatalf("unexpected piece hash count: got %d", len(tf.PieceHashes))
}
}
func TestOpenRejectsPieceCountMismatch(t *testing.T) {
t.Parallel()
info := "d6:lengthi10e4:name8:test.txt12:piece lengthi4e6:pieces40:aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbe"
torrent := "d8:announce14:http://tracker4:info" + info + "e"
path := writeTempTorrent(t, torrent)
_, err := Open(path)
if err == nil {
t.Fatal("expected Open to fail for piece count mismatch")
}
}
func TestOpenParsesAnnounceListAndDeduplicatesTrackers(t *testing.T) {
t.Parallel()
info := "d6:lengthi5e4:name8:test.txt12:piece lengthi16384e6:pieces20:aaaaaaaaaaaaaaaaaaaae"
torrent := "d8:announce14:http://tracker13:announce-listll14:http://tracker17:udp://tracker.oneel17:udp://tracker.one17:udp://tracker.twoee4:info" + info + "e"
path := writeTempTorrent(t, torrent)
tf, err := Open(path)
if err != nil {
t.Fatalf("Open returned error: %v", err)
}
expected := []string{
"http://tracker",
"udp://tracker.one",
"udp://tracker.two",
}
if len(tf.Trackers) != len(expected) {
t.Fatalf("unexpected trackers length: got %d want %d (%#v)", len(tf.Trackers), len(expected), tf.Trackers)
}
for i := range expected {
if tf.Trackers[i] != expected[i] {
t.Fatalf("unexpected tracker[%d]: got %q want %q", i, tf.Trackers[i], expected[i])
}
}
}
func writeTempTorrent(t *testing.T, data string) string {
t.Helper()
dir := t.TempDir()
path := filepath.Join(dir, "test.torrent")
if err := os.WriteFile(path, []byte(data), 0o600); err != nil {
t.Fatalf("failed to write temp torrent file: %v", err)
}
return path
}