go fmt [ci skip]
This commit is contained in:
parent
cf36519c5e
commit
6549f49e26
10 changed files with 1735 additions and 1735 deletions
|
@ -6,83 +6,83 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Duration struct {
|
type Duration struct {
|
||||||
time.Duration
|
time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Duration) MarshalJSON() ([]byte, error) {
|
func (d *Duration) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(d.String())
|
return json.Marshal(d.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
var str string
|
var str string
|
||||||
err := json.Unmarshal(b, &str)
|
err := json.Unmarshal(b, &str)
|
||||||
d.Duration, err = time.ParseDuration(str)
|
d.Duration, err = time.ParseDuration(str)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataStore represents the configuration used to connect to a data store.
|
// DataStore represents the configuration used to connect to a data store.
|
||||||
type DataStore struct {
|
type DataStore struct {
|
||||||
Driver string `json:"driver"`
|
Driver string `json:"driver"`
|
||||||
Network string `json:"network`
|
Network string `json:"network`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port string `json:"port"`
|
Port string `json:"port"`
|
||||||
Username string `json:"user"`
|
Username string `json:"user"`
|
||||||
Password string `json:"pass"`
|
Password string `json:"pass"`
|
||||||
Schema string `json:"schema,omitempty"`
|
Schema string `json:"schema,omitempty"`
|
||||||
Encoding string `json:"encoding,omitempty"`
|
Encoding string `json:"encoding,omitempty"`
|
||||||
Prefix string `json:"prefix,omitempty"`
|
Prefix string `json:"prefix,omitempty"`
|
||||||
|
|
||||||
MaxIdleConns int `json:"max_idle_conns,omitempty"`
|
MaxIdleConns int `json:"max_idle_conns,omitempty"`
|
||||||
IdleTimeout *Duration `json:"idle_timeout,omitempty"`
|
IdleTimeout *Duration `json:"idle_timeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config represents a configuration for a server.Server.
|
// Config represents a configuration for a server.Server.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Addr string `json:"addr"`
|
Addr string `json:"addr"`
|
||||||
PubAddr string `json:"pub_addr"`
|
PubAddr string `json:"pub_addr"`
|
||||||
Cache DataStore `json:"cache"`
|
Cache DataStore `json:"cache"`
|
||||||
Storage DataStore `json:"storage"`
|
Storage DataStore `json:"storage"`
|
||||||
|
|
||||||
Private bool `json:"private"`
|
Private bool `json:"private"`
|
||||||
Freeleech bool `json:"freeleech"`
|
Freeleech bool `json:"freeleech"`
|
||||||
Slots bool `json:"slots"`
|
Slots bool `json:"slots"`
|
||||||
|
|
||||||
Announce Duration `json:"announce"`
|
Announce Duration `json:"announce"`
|
||||||
MinAnnounce Duration `json:"min_announce"`
|
MinAnnounce Duration `json:"min_announce"`
|
||||||
ReadTimeout Duration `json:"read_timeout"`
|
ReadTimeout Duration `json:"read_timeout"`
|
||||||
DefaultNumWant int `json:"default_num_want"`
|
DefaultNumWant int `json:"default_num_want"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open is a shortcut to open a file, read it, and generate a Config.
|
// Open is a shortcut to open a file, read it, and generate a Config.
|
||||||
// It supports relative and absolute paths.
|
// It supports relative and absolute paths.
|
||||||
func Open(path string) (*Config, error) {
|
func Open(path string) (*Config, error) {
|
||||||
expandedPath := os.ExpandEnv(path)
|
expandedPath := os.ExpandEnv(path)
|
||||||
f, err := os.Open(expandedPath)
|
f, err := os.Open(expandedPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
conf, err := newConfig(f)
|
conf, err := newConfig(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New decodes JSON from a Reader into a Config.
|
// New decodes JSON from a Reader into a Config.
|
||||||
func newConfig(raw io.Reader) (*Config, error) {
|
func newConfig(raw io.Reader) (*Config, error) {
|
||||||
conf := &Config{}
|
conf := &Config{}
|
||||||
err := json.NewDecoder(raw).Decode(conf)
|
err := json.NewDecoder(raw).Decode(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,351 +5,351 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/storage"
|
"github.com/pushrax/chihaya/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
||||||
// Parse the required parameters off of a query
|
// Parse the required parameters off of a query
|
||||||
compact, numWant, infohash, peerID, event, ip, port, uploaded, downloaded, left, err := s.validateAnnounceQuery(r)
|
compact, numWant, infohash, peerID, event, ip, port, uploaded, downloaded, left, err := s.validateAnnounceQuery(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail(err, w, r)
|
fail(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a connection to the tracker db
|
// Get a connection to the tracker db
|
||||||
conn, err := s.dbConnPool.Get()
|
conn, err := s.dbConnPool.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the user's passkey
|
// Validate the user's passkey
|
||||||
passkey, _ := path.Split(r.URL.Path)
|
passkey, _ := path.Split(r.URL.Path)
|
||||||
user, err := validateUser(conn, passkey)
|
user, err := validateUser(conn, passkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail(err, w, r)
|
fail(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user's client is whitelisted
|
// Check if the user's client is whitelisted
|
||||||
whitelisted, err := conn.ClientWhitelisted(parsePeerID(peerID))
|
whitelisted, err := conn.ClientWhitelisted(parsePeerID(peerID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if !whitelisted {
|
if !whitelisted {
|
||||||
fail(errors.New("Your client is not approved"), w, r)
|
fail(errors.New("Your client is not approved"), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the specified torrent
|
// Find the specified torrent
|
||||||
torrent, exists, err := conn.FindTorrent(infohash)
|
torrent, exists, err := conn.FindTorrent(infohash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
fail(errors.New("This torrent does not exist"), w, r)
|
fail(errors.New("This torrent does not exist"), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the torrent was pruned and the user is seeding, unprune it
|
// If the torrent was pruned and the user is seeding, unprune it
|
||||||
if !torrent.Active && left == 0 {
|
if !torrent.Active && left == 0 {
|
||||||
err := conn.MarkActive(torrent)
|
err := conn.MarkActive(torrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new peer object from the request
|
// Create a new peer object from the request
|
||||||
peer := &storage.Peer{
|
peer := &storage.Peer{
|
||||||
ID: peerID,
|
ID: peerID,
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
TorrentID: torrent.ID,
|
TorrentID: torrent.ID,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Port: port,
|
Port: port,
|
||||||
Uploaded: uploaded,
|
Uploaded: uploaded,
|
||||||
Downloaded: downloaded,
|
Downloaded: downloaded,
|
||||||
Left: left,
|
Left: left,
|
||||||
LastAnnounce: time.Now().Unix(),
|
LastAnnounce: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for the user in in the pool of seeders and leechers
|
// Look for the user in in the pool of seeders and leechers
|
||||||
_, seeder := torrent.Seeders[storage.PeerMapKey(peer)]
|
_, seeder := torrent.Seeders[storage.PeerMapKey(peer)]
|
||||||
_, leecher := torrent.Leechers[storage.PeerMapKey(peer)]
|
_, leecher := torrent.Leechers[storage.PeerMapKey(peer)]
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// Guarantee that no user is in both pools
|
// Guarantee that no user is in both pools
|
||||||
case seeder && leecher:
|
case seeder && leecher:
|
||||||
if left == 0 {
|
if left == 0 {
|
||||||
err := conn.RemoveLeecher(torrent, peer)
|
err := conn.RemoveLeecher(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
leecher = false
|
leecher = false
|
||||||
} else {
|
} else {
|
||||||
err := conn.RemoveSeeder(torrent, peer)
|
err := conn.RemoveSeeder(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
seeder = false
|
seeder = false
|
||||||
}
|
}
|
||||||
|
|
||||||
case seeder:
|
case seeder:
|
||||||
// Update the peer with the stats from the request
|
// Update the peer with the stats from the request
|
||||||
err := conn.SetSeeder(torrent, peer)
|
err := conn.SetSeeder(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case leecher:
|
case leecher:
|
||||||
// Update the peer with the stats from the request
|
// Update the peer with the stats from the request
|
||||||
err := conn.SetLeecher(torrent, peer)
|
err := conn.SetLeecher(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Check the user's slots to see if they're allowed to leech
|
// Check the user's slots to see if they're allowed to leech
|
||||||
if s.conf.Slots && user.Slots != -1 && left != 0 {
|
if s.conf.Slots && user.Slots != -1 && left != 0 {
|
||||||
if user.SlotsUsed >= user.Slots {
|
if user.SlotsUsed >= user.Slots {
|
||||||
fail(errors.New("You've run out of download slots."), w, r)
|
fail(errors.New("You've run out of download slots."), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if left == 0 {
|
if left == 0 {
|
||||||
// Save the peer as a new seeder
|
// Save the peer as a new seeder
|
||||||
err := conn.AddSeeder(torrent, peer)
|
err := conn.AddSeeder(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Save the peer as a new leecher and increment the user's slots
|
// Save the peer as a new leecher and increment the user's slots
|
||||||
err := conn.IncrementSlots(user)
|
err := conn.IncrementSlots(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
err = conn.AddLeecher(torrent, peer)
|
err = conn.AddLeecher(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle any events in the request
|
// Handle any events in the request
|
||||||
switch {
|
switch {
|
||||||
case event == "stopped" || event == "paused":
|
case event == "stopped" || event == "paused":
|
||||||
if seeder {
|
if seeder {
|
||||||
err := conn.RemoveSeeder(torrent, peer)
|
err := conn.RemoveSeeder(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if leecher {
|
if leecher {
|
||||||
err := conn.RemoveLeecher(torrent, peer)
|
err := conn.RemoveLeecher(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
err = conn.DecrementSlots(user)
|
err = conn.DecrementSlots(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case event == "completed":
|
case event == "completed":
|
||||||
err := conn.RecordSnatch(user, torrent)
|
err := conn.RecordSnatch(user, torrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if leecher {
|
if leecher {
|
||||||
err := conn.LeecherFinished(torrent, peer)
|
err := conn.LeecherFinished(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case leecher && left == 0:
|
case leecher && left == 0:
|
||||||
// A leecher completed but the event was never received
|
// A leecher completed but the event was never received
|
||||||
err := conn.LeecherFinished(torrent, peer)
|
err := conn.LeecherFinished(torrent, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ip != peer.IP || port != peer.Port {
|
if ip != peer.IP || port != peer.Port {
|
||||||
peer.Port = port
|
peer.Port = port
|
||||||
peer.IP = ip
|
peer.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the response
|
// Generate the response
|
||||||
seedCount := len(torrent.Seeders)
|
seedCount := len(torrent.Seeders)
|
||||||
leechCount := len(torrent.Leechers)
|
leechCount := len(torrent.Leechers)
|
||||||
|
|
||||||
writeBencoded(w, "d")
|
writeBencoded(w, "d")
|
||||||
writeBencoded(w, "complete")
|
writeBencoded(w, "complete")
|
||||||
writeBencoded(w, seedCount)
|
writeBencoded(w, seedCount)
|
||||||
writeBencoded(w, "incomplete")
|
writeBencoded(w, "incomplete")
|
||||||
writeBencoded(w, leechCount)
|
writeBencoded(w, leechCount)
|
||||||
writeBencoded(w, "interval")
|
writeBencoded(w, "interval")
|
||||||
writeBencoded(w, s.conf.Announce.Duration)
|
writeBencoded(w, s.conf.Announce.Duration)
|
||||||
writeBencoded(w, "min interval")
|
writeBencoded(w, "min interval")
|
||||||
writeBencoded(w, s.conf.MinAnnounce.Duration)
|
writeBencoded(w, s.conf.MinAnnounce.Duration)
|
||||||
|
|
||||||
if numWant > 0 && event != "stopped" && event != "paused" {
|
if numWant > 0 && event != "stopped" && event != "paused" {
|
||||||
writeBencoded(w, "peers")
|
writeBencoded(w, "peers")
|
||||||
var peerCount, count int
|
var peerCount, count int
|
||||||
|
|
||||||
if compact {
|
if compact {
|
||||||
if left > 0 {
|
if left > 0 {
|
||||||
peerCount = minInt(numWant, leechCount)
|
peerCount = minInt(numWant, leechCount)
|
||||||
} else {
|
} else {
|
||||||
peerCount = minInt(numWant, leechCount+seedCount-1)
|
peerCount = minInt(numWant, leechCount+seedCount-1)
|
||||||
}
|
}
|
||||||
writeBencoded(w, strconv.Itoa(peerCount*6))
|
writeBencoded(w, strconv.Itoa(peerCount*6))
|
||||||
writeBencoded(w, ":")
|
writeBencoded(w, ":")
|
||||||
} else {
|
} else {
|
||||||
writeBencoded(w, "l")
|
writeBencoded(w, "l")
|
||||||
}
|
}
|
||||||
|
|
||||||
if left > 0 {
|
if left > 0 {
|
||||||
// If they're seeding, give them only leechers
|
// If they're seeding, give them only leechers
|
||||||
writeLeechers(w, torrent, count, numWant, compact)
|
writeLeechers(w, torrent, count, numWant, compact)
|
||||||
} else {
|
} else {
|
||||||
// If they're leeching, prioritize giving them seeders
|
// If they're leeching, prioritize giving them seeders
|
||||||
writeSeeders(w, torrent, count, numWant, compact)
|
writeSeeders(w, torrent, count, numWant, compact)
|
||||||
writeLeechers(w, torrent, count, numWant, compact)
|
writeLeechers(w, torrent, count, numWant, compact)
|
||||||
}
|
}
|
||||||
|
|
||||||
if compact && peerCount != count {
|
if compact && peerCount != count {
|
||||||
log.Panicf("Calculated peer count (%d) != real count (%d)", peerCount, count)
|
log.Panicf("Calculated peer count (%d) != real count (%d)", peerCount, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !compact {
|
if !compact {
|
||||||
writeBencoded(w, "e")
|
writeBencoded(w, "e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeBencoded(w, "e")
|
writeBencoded(w, "e")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) {
|
func (s Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) {
|
||||||
pq, err := parseQuery(r.URL.RawQuery)
|
pq, err := parseQuery(r.URL.RawQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, 0, "", "", "", "", 0, 0, 0, 0, err
|
return false, 0, "", "", "", "", 0, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
compact = pq.Params["compact"] == "1"
|
compact = pq.Params["compact"] == "1"
|
||||||
numWant = requestedPeerCount(s.conf.DefaultNumWant, pq)
|
numWant = requestedPeerCount(s.conf.DefaultNumWant, pq)
|
||||||
infohash, _ = pq.Params["info_hash"]
|
infohash, _ = pq.Params["info_hash"]
|
||||||
peerID, _ = pq.Params["peer_id"]
|
peerID, _ = pq.Params["peer_id"]
|
||||||
event, _ = pq.Params["event"]
|
event, _ = pq.Params["event"]
|
||||||
ip, _ = requestedIP(r, pq)
|
ip, _ = requestedIP(r, pq)
|
||||||
port, portErr := pq.getUint64("port")
|
port, portErr := pq.getUint64("port")
|
||||||
uploaded, uploadedErr := pq.getUint64("uploaded")
|
uploaded, uploadedErr := pq.getUint64("uploaded")
|
||||||
downloaded, downloadedErr := pq.getUint64("downloaded")
|
downloaded, downloadedErr := pq.getUint64("downloaded")
|
||||||
left, leftErr := pq.getUint64("left")
|
left, leftErr := pq.getUint64("left")
|
||||||
|
|
||||||
if infohash == "" ||
|
if infohash == "" ||
|
||||||
peerID == "" ||
|
peerID == "" ||
|
||||||
ip == "" ||
|
ip == "" ||
|
||||||
portErr != nil ||
|
portErr != nil ||
|
||||||
uploadedErr != nil ||
|
uploadedErr != nil ||
|
||||||
downloadedErr != nil ||
|
downloadedErr != nil ||
|
||||||
leftErr != nil {
|
leftErr != nil {
|
||||||
return false, 0, "", "", "", "", 0, 0, 0, 0, errors.New("Malformed request")
|
return false, 0, "", "", "", "", 0, 0, 0, 0, errors.New("Malformed request")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestedPeerCount(fallback int, pq *parsedQuery) int {
|
func requestedPeerCount(fallback int, pq *parsedQuery) int {
|
||||||
if numWantStr, exists := pq.Params["numWant"]; exists {
|
if numWantStr, exists := pq.Params["numWant"]; exists {
|
||||||
numWant, err := strconv.Atoi(numWantStr)
|
numWant, err := strconv.Atoi(numWantStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
return numWant
|
return numWant
|
||||||
}
|
}
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestedIP(r *http.Request, pq *parsedQuery) (string, error) {
|
func requestedIP(r *http.Request, pq *parsedQuery) (string, error) {
|
||||||
ip, ok := pq.Params["ip"]
|
ip, ok := pq.Params["ip"]
|
||||||
ipv4, okv4 := pq.Params["ipv4"]
|
ipv4, okv4 := pq.Params["ipv4"]
|
||||||
xRealIPs, xRealOk := pq.Params["X-Real-Ip"]
|
xRealIPs, xRealOk := pq.Params["X-Real-Ip"]
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case ok:
|
case ok:
|
||||||
return ip, nil
|
return ip, nil
|
||||||
|
|
||||||
case okv4:
|
case okv4:
|
||||||
return ipv4, nil
|
return ipv4, nil
|
||||||
|
|
||||||
case xRealOk && len(xRealIPs) > 0:
|
case xRealOk && len(xRealIPs) > 0:
|
||||||
return string(xRealIPs[0]), nil
|
return string(xRealIPs[0]), nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
portIndex := len(r.RemoteAddr) - 1
|
portIndex := len(r.RemoteAddr) - 1
|
||||||
for ; portIndex >= 0; portIndex-- {
|
for ; portIndex >= 0; portIndex-- {
|
||||||
if r.RemoteAddr[portIndex] == ':' {
|
if r.RemoteAddr[portIndex] == ':' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if portIndex != -1 {
|
if portIndex != -1 {
|
||||||
return r.RemoteAddr[0:portIndex], nil
|
return r.RemoteAddr[0:portIndex], nil
|
||||||
}
|
}
|
||||||
return "", errors.New("Failed to parse IP address")
|
return "", errors.New("Failed to parse IP address")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func minInt(a, b int) int {
|
func minInt(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeSeeders(w http.ResponseWriter, t *storage.Torrent, count, numWant int, compact bool) {
|
func writeSeeders(w http.ResponseWriter, t *storage.Torrent, count, numWant int, compact bool) {
|
||||||
for _, seed := range t.Seeders {
|
for _, seed := range t.Seeders {
|
||||||
if count >= numWant {
|
if count >= numWant {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if compact {
|
if compact {
|
||||||
// TODO writeBencoded(w, compactAddr)
|
// TODO writeBencoded(w, compactAddr)
|
||||||
} else {
|
} else {
|
||||||
writeBencoded(w, "d")
|
writeBencoded(w, "d")
|
||||||
writeBencoded(w, "ip")
|
writeBencoded(w, "ip")
|
||||||
writeBencoded(w, seed.IP)
|
writeBencoded(w, seed.IP)
|
||||||
writeBencoded(w, "peer id")
|
writeBencoded(w, "peer id")
|
||||||
writeBencoded(w, seed.ID)
|
writeBencoded(w, seed.ID)
|
||||||
writeBencoded(w, "port")
|
writeBencoded(w, "port")
|
||||||
writeBencoded(w, seed.Port)
|
writeBencoded(w, seed.Port)
|
||||||
writeBencoded(w, "e")
|
writeBencoded(w, "e")
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLeechers(w http.ResponseWriter, t *storage.Torrent, count, numWant int, compact bool) {
|
func writeLeechers(w http.ResponseWriter, t *storage.Torrent, count, numWant int, compact bool) {
|
||||||
for _, leech := range t.Leechers {
|
for _, leech := range t.Leechers {
|
||||||
if count >= numWant {
|
if count >= numWant {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if compact {
|
if compact {
|
||||||
// TODO writeBencoded(w, compactAddr)
|
// TODO writeBencoded(w, compactAddr)
|
||||||
} else {
|
} else {
|
||||||
writeBencoded(w, "d")
|
writeBencoded(w, "d")
|
||||||
writeBencoded(w, "ip")
|
writeBencoded(w, "ip")
|
||||||
writeBencoded(w, leech.IP)
|
writeBencoded(w, leech.IP)
|
||||||
writeBencoded(w, "peer id")
|
writeBencoded(w, "peer id")
|
||||||
writeBencoded(w, leech.ID)
|
writeBencoded(w, leech.ID)
|
||||||
writeBencoded(w, "port")
|
writeBencoded(w, "port")
|
||||||
writeBencoded(w, leech.Port)
|
writeBencoded(w, leech.Port)
|
||||||
writeBencoded(w, "e")
|
writeBencoded(w, "e")
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
server/scrape.go
114
server/scrape.go
|
@ -5,72 +5,72 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/storage"
|
"github.com/pushrax/chihaya/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request) {
|
||||||
// Parse the query
|
// Parse the query
|
||||||
pq, err := parseQuery(r.URL.RawQuery)
|
pq, err := parseQuery(r.URL.RawQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail(errors.New("Error parsing query"), w, r)
|
fail(errors.New("Error parsing query"), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a connection to the tracker db
|
// Get a connection to the tracker db
|
||||||
conn, err := s.dbConnPool.Get()
|
conn, err := s.dbConnPool.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and validate the user
|
// Find and validate the user
|
||||||
passkey, _ := path.Split(r.URL.Path)
|
passkey, _ := path.Split(r.URL.Path)
|
||||||
_, err = validateUser(conn, passkey)
|
_, err = validateUser(conn, passkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail(err, w, r)
|
fail(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
io.WriteString(w, "d")
|
io.WriteString(w, "d")
|
||||||
writeBencoded(w, "files")
|
writeBencoded(w, "files")
|
||||||
if pq.Infohashes != nil {
|
if pq.Infohashes != nil {
|
||||||
for _, infohash := range pq.Infohashes {
|
for _, infohash := range pq.Infohashes {
|
||||||
torrent, exists, err := conn.FindTorrent(infohash)
|
torrent, exists, err := conn.FindTorrent(infohash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if exists {
|
if exists {
|
||||||
writeBencoded(w, infohash)
|
writeBencoded(w, infohash)
|
||||||
writeScrapeInfo(w, torrent)
|
writeScrapeInfo(w, torrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if infohash, exists := pq.Params["info_hash"]; exists {
|
} else if infohash, exists := pq.Params["info_hash"]; exists {
|
||||||
torrent, exists, err := conn.FindTorrent(infohash)
|
torrent, exists, err := conn.FindTorrent(infohash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if exists {
|
if exists {
|
||||||
writeBencoded(w, infohash)
|
writeBencoded(w, infohash)
|
||||||
writeScrapeInfo(w, torrent)
|
writeScrapeInfo(w, torrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io.WriteString(w, "e")
|
io.WriteString(w, "e")
|
||||||
|
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeScrapeInfo(w io.Writer, torrent *storage.Torrent) {
|
func writeScrapeInfo(w io.Writer, torrent *storage.Torrent) {
|
||||||
io.WriteString(w, "d")
|
io.WriteString(w, "d")
|
||||||
writeBencoded(w, "complete")
|
writeBencoded(w, "complete")
|
||||||
writeBencoded(w, len(torrent.Seeders))
|
writeBencoded(w, len(torrent.Seeders))
|
||||||
writeBencoded(w, "downloaded")
|
writeBencoded(w, "downloaded")
|
||||||
writeBencoded(w, torrent.Snatches)
|
writeBencoded(w, torrent.Snatches)
|
||||||
writeBencoded(w, "incomplete")
|
writeBencoded(w, "incomplete")
|
||||||
writeBencoded(w, len(torrent.Leechers))
|
writeBencoded(w, len(torrent.Leechers))
|
||||||
io.WriteString(w, "e")
|
io.WriteString(w, "e")
|
||||||
}
|
}
|
||||||
|
|
196
server/server.go
196
server/server.go
|
@ -6,140 +6,140 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/etix/stoppableListener"
|
"github.com/etix/stoppableListener"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/config"
|
"github.com/pushrax/chihaya/config"
|
||||||
"github.com/pushrax/chihaya/storage"
|
"github.com/pushrax/chihaya/storage"
|
||||||
"github.com/pushrax/chihaya/storage/tracker"
|
"github.com/pushrax/chihaya/storage/tracker"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
conf *config.Config
|
conf *config.Config
|
||||||
listener *stoppableListener.StoppableListener
|
listener *stoppableListener.StoppableListener
|
||||||
dbConnPool tracker.Pool
|
dbConnPool tracker.Pool
|
||||||
|
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
|
|
||||||
deltaRequests int64
|
deltaRequests int64
|
||||||
rpm int64
|
rpm int64
|
||||||
|
|
||||||
http.Server
|
http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(conf *config.Config) (*Server, error) {
|
func New(conf *config.Config) (*Server, error) {
|
||||||
pool, err := tracker.Open(&conf.Cache)
|
pool, err := tracker.Open(&conf.Cache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
conf: conf,
|
conf: conf,
|
||||||
dbConnPool: pool,
|
dbConnPool: pool,
|
||||||
Server: http.Server{
|
Server: http.Server{
|
||||||
Addr: conf.Addr,
|
Addr: conf.Addr,
|
||||||
ReadTimeout: conf.ReadTimeout.Duration,
|
ReadTimeout: conf.ReadTimeout.Duration,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s.Server.Handler = s
|
s.Server.Handler = s
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ListenAndServe() error {
|
func (s *Server) ListenAndServe() error {
|
||||||
l, err := net.Listen("tcp", s.Addr)
|
l, err := net.Listen("tcp", s.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sl := stoppableListener.Handle(l)
|
sl := stoppableListener.Handle(l)
|
||||||
s.listener = sl
|
s.listener = sl
|
||||||
s.startTime = time.Now()
|
s.startTime = time.Now()
|
||||||
|
|
||||||
go s.updateStats()
|
go s.updateStats()
|
||||||
s.Serve(s.listener)
|
s.Serve(s.listener)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Stop() error {
|
func (s *Server) Stop() error {
|
||||||
s.listener.Stop <- true
|
s.listener.Stop <- true
|
||||||
err := s.dbConnPool.Close()
|
err := s.dbConnPool.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.listener.Close()
|
return s.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer atomic.AddInt64(&s.deltaRequests, 1)
|
defer atomic.AddInt64(&s.deltaRequests, 1)
|
||||||
r.Close = true
|
r.Close = true
|
||||||
|
|
||||||
switch r.URL.Path {
|
switch r.URL.Path {
|
||||||
case "/stats":
|
case "/stats":
|
||||||
s.serveStats(w, r)
|
s.serveStats(w, r)
|
||||||
return
|
return
|
||||||
case "/add":
|
case "/add":
|
||||||
s.serveAdd(w, r)
|
s.serveAdd(w, r)
|
||||||
return
|
return
|
||||||
case "/remove":
|
case "/remove":
|
||||||
s.serveRemove(w, r)
|
s.serveRemove(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, action := path.Split(r.URL.Path)
|
_, action := path.Split(r.URL.Path)
|
||||||
switch action {
|
switch action {
|
||||||
case "announce":
|
case "announce":
|
||||||
s.serveAnnounce(w, r)
|
s.serveAnnounce(w, r)
|
||||||
return
|
return
|
||||||
case "scrape":
|
case "scrape":
|
||||||
s.serveScrape(w, r)
|
s.serveScrape(w, r)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
fail(errors.New("Unknown action"), w, r)
|
fail(errors.New("Unknown action"), w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fail(err error, w http.ResponseWriter, r *http.Request) {
|
func fail(err error, w http.ResponseWriter, r *http.Request) {
|
||||||
errmsg := err.Error()
|
errmsg := err.Error()
|
||||||
message := "d14:failure reason" + strconv.Itoa(len(errmsg)) + ":" + errmsg + "e"
|
message := "d14:failure reason" + strconv.Itoa(len(errmsg)) + ":" + errmsg + "e"
|
||||||
length, _ := io.WriteString(w, message)
|
length, _ := io.WriteString(w, message)
|
||||||
w.Header().Add("Content-Length", string(length))
|
w.Header().Add("Content-Length", string(length))
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateUser(conn tracker.Conn, dir string) (*storage.User, error) {
|
func validateUser(conn tracker.Conn, dir string) (*storage.User, error) {
|
||||||
if len(dir) != 34 {
|
if len(dir) != 34 {
|
||||||
return nil, errors.New("Passkey is invalid")
|
return nil, errors.New("Passkey is invalid")
|
||||||
}
|
}
|
||||||
passkey := dir[1:33]
|
passkey := dir[1:33]
|
||||||
|
|
||||||
user, exists, err := conn.FindUser(passkey)
|
user, exists, err := conn.FindUser(passkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("server: %s", err)
|
log.Panicf("server: %s", err)
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, errors.New("User not found")
|
return nil, errors.New("User not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a peer_id and returns a ClientID
|
// Takes a peer_id and returns a ClientID
|
||||||
func parsePeerID(peerID string) (clientID string) {
|
func parsePeerID(peerID string) (clientID string) {
|
||||||
if peerID[0] == '-' {
|
if peerID[0] == '-' {
|
||||||
clientID = peerID[1:7]
|
clientID = peerID[1:7]
|
||||||
} else {
|
} else {
|
||||||
clientID = peerID[0:6]
|
clientID = peerID[0:6]
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,35 +5,35 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/config"
|
"github.com/pushrax/chihaya/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stats struct {
|
type stats struct {
|
||||||
Uptime config.Duration `json:"uptime"`
|
Uptime config.Duration `json:"uptime"`
|
||||||
RPM int64 `json:"req_per_min"`
|
RPM int64 `json:"req_per_min"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) serveStats(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) serveStats(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
stats, _ := json.Marshal(&stats{
|
stats, _ := json.Marshal(&stats{
|
||||||
config.Duration{time.Now().Sub(s.startTime)},
|
config.Duration{time.Now().Sub(s.startTime)},
|
||||||
s.rpm,
|
s.rpm,
|
||||||
})
|
})
|
||||||
|
|
||||||
length, _ := w.Write(stats)
|
length, _ := w.Write(stats)
|
||||||
w.Header().Set("Content-Length", string(length))
|
w.Header().Set("Content-Length", string(length))
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) updateStats() {
|
func (s *Server) updateStats() {
|
||||||
for _ = range time.NewTicker(time.Minute).C {
|
for _ = range time.NewTicker(time.Minute).C {
|
||||||
s.rpm = s.deltaRequests
|
s.rpm = s.deltaRequests
|
||||||
atomic.StoreInt64(&s.deltaRequests, 0)
|
atomic.StoreInt64(&s.deltaRequests, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,51 +5,51 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/config"
|
"github.com/pushrax/chihaya/config"
|
||||||
|
|
||||||
_ "github.com/pushrax/chihaya/storage/backend/batter"
|
_ "github.com/pushrax/chihaya/storage/backend/batter"
|
||||||
_ "github.com/pushrax/chihaya/storage/tracker/redis"
|
_ "github.com/pushrax/chihaya/storage/tracker/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestServer() (*Server, error) {
|
func newTestServer() (*Server, error) {
|
||||||
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := New(testConfig)
|
s, err := New(testConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStats(t *testing.T) {
|
func TestStats(t *testing.T) {
|
||||||
s, err := newTestServer()
|
s, err := newTestServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := http.NewRequest("GET", "127.0.0.1:80/stats", nil)
|
r, err := http.NewRequest("GET", "127.0.0.1:80/stats", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
s.serveStats(w, r)
|
s.serveStats(w, r)
|
||||||
|
|
||||||
if w.Code != 200 {
|
if w.Code != 200 {
|
||||||
t.Error(errors.New("/stats did not return HTTP 200"))
|
t.Error(errors.New("/stats did not return HTTP 200"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.Header()["Content-Type"][0] != "application/json" {
|
if w.Header()["Content-Type"][0] != "application/json" {
|
||||||
t.Error(errors.New("/stats did not return the proper Content-Type header"))
|
t.Error(errors.New("/stats did not return the proper Content-Type header"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,559 +5,559 @@
|
||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/config"
|
"github.com/pushrax/chihaya/config"
|
||||||
"github.com/pushrax/chihaya/storage"
|
"github.com/pushrax/chihaya/storage"
|
||||||
"github.com/pushrax/chihaya/storage/tracker"
|
"github.com/pushrax/chihaya/storage/tracker"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTestConn() tracker.Conn {
|
func createTestConn() tracker.Conn {
|
||||||
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
conf := &testConfig.Cache
|
conf := &testConfig.Cache
|
||||||
|
|
||||||
testPool, err := tracker.Open(conf)
|
testPool, err := tracker.Open(conf)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
newConn, err := testPool.Get()
|
newConn, err := testPool.Get()
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
return newConn
|
return newConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindUserSuccess(t *testing.T) {
|
func TestFindUserSuccess(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
|
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("user not found", testUser)
|
t.Error("user not found", testUser)
|
||||||
}
|
}
|
||||||
if *foundUser != *testUser {
|
if *foundUser != *testUser {
|
||||||
t.Error("found user mismatch", *foundUser, testUser)
|
t.Error("found user mismatch", *foundUser, testUser)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindUserFail(t *testing.T) {
|
func TestFindUserFail(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
|
|
||||||
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("user found", foundUser)
|
t.Error("user found", foundUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveUser(t *testing.T) {
|
func TestRemoveUser(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
|
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
err := conn.RemoveUser(testUser)
|
err := conn.RemoveUser(testUser)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("removed user found", foundUser)
|
t.Error("removed user found", foundUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindTorrentSuccess(t *testing.T) {
|
func TestFindTorrentSuccess(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
|
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("torrent not found", testTorrent)
|
t.Error("torrent not found", testTorrent)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(foundTorrent, testTorrent) {
|
if !reflect.DeepEqual(foundTorrent, testTorrent) {
|
||||||
t.Error("found torrent mismatch", foundTorrent, testTorrent)
|
t.Error("found torrent mismatch", foundTorrent, testTorrent)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindTorrentFail(t *testing.T) {
|
func TestFindTorrentFail(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
|
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("torrent found", foundTorrent)
|
t.Error("torrent found", foundTorrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveTorrent(t *testing.T) {
|
func TestRemoveTorrent(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
|
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("removed torrent found", foundTorrent)
|
t.Error("removed torrent found", foundTorrent)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientWhitelistSuccess(t *testing.T) {
|
func TestClientWhitelistSuccess(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testPeerID := "-lt0D30-"
|
testPeerID := "-lt0D30-"
|
||||||
|
|
||||||
panicOnErr(conn.WhitelistClient(testPeerID))
|
panicOnErr(conn.WhitelistClient(testPeerID))
|
||||||
found, err := conn.ClientWhitelisted(testPeerID)
|
found, err := conn.ClientWhitelisted(testPeerID)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("peerID not found", testPeerID)
|
t.Error("peerID not found", testPeerID)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientWhitelistFail(t *testing.T) {
|
func TestClientWhitelistFail(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testPeerID2 := "TIX0192"
|
testPeerID2 := "TIX0192"
|
||||||
|
|
||||||
found, err := conn.ClientWhitelisted(testPeerID2)
|
found, err := conn.ClientWhitelisted(testPeerID2)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("peerID found", testPeerID2)
|
t.Error("peerID found", testPeerID2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecordSnatch(t *testing.T) {
|
func TestRecordSnatch(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
|
|
||||||
userSnatches := testUser.Snatches
|
userSnatches := testUser.Snatches
|
||||||
torrentSnatches := testTorrent.Snatches
|
torrentSnatches := testTorrent.Snatches
|
||||||
|
|
||||||
panicOnErr(conn.RecordSnatch(testUser, testTorrent))
|
panicOnErr(conn.RecordSnatch(testUser, testTorrent))
|
||||||
|
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
if testUser.Snatches != userSnatches+1 {
|
if testUser.Snatches != userSnatches+1 {
|
||||||
t.Error("snatch not recorded to local user", testUser.Snatches, userSnatches+1)
|
t.Error("snatch not recorded to local user", testUser.Snatches, userSnatches+1)
|
||||||
}
|
}
|
||||||
if testTorrent.Snatches != torrentSnatches+1 {
|
if testTorrent.Snatches != torrentSnatches+1 {
|
||||||
t.Error("snatch not recorded to local torrent")
|
t.Error("snatch not recorded to local torrent")
|
||||||
}
|
}
|
||||||
if foundUser.Snatches != userSnatches+1 {
|
if foundUser.Snatches != userSnatches+1 {
|
||||||
t.Error("snatch not recorded to cached user", foundUser.Snatches, userSnatches+1)
|
t.Error("snatch not recorded to cached user", foundUser.Snatches, userSnatches+1)
|
||||||
}
|
}
|
||||||
if foundTorrent.Snatches != torrentSnatches+1 {
|
if foundTorrent.Snatches != torrentSnatches+1 {
|
||||||
t.Error("snatch not recorded to cached torrent")
|
t.Error("snatch not recorded to cached torrent")
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarkActive(t *testing.T) {
|
func TestMarkActive(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
testTorrent.Active = false
|
testTorrent.Active = false
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
|
|
||||||
panicOnErr(conn.MarkActive(testTorrent))
|
panicOnErr(conn.MarkActive(testTorrent))
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
if foundTorrent.Active != true {
|
if foundTorrent.Active != true {
|
||||||
t.Error("cached torrent not activated")
|
t.Error("cached torrent not activated")
|
||||||
}
|
}
|
||||||
if testTorrent.Active != true {
|
if testTorrent.Active != true {
|
||||||
t.Error("cached torrent not activated")
|
t.Error("cached torrent not activated")
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientWhitelistRemove(t *testing.T) {
|
func TestClientWhitelistRemove(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testPeerID := "-lt0D30-"
|
testPeerID := "-lt0D30-"
|
||||||
panicOnErr(conn.WhitelistClient(testPeerID))
|
panicOnErr(conn.WhitelistClient(testPeerID))
|
||||||
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
||||||
|
|
||||||
found, err := conn.ClientWhitelisted(testPeerID)
|
found, err := conn.ClientWhitelisted(testPeerID)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("removed peerID found", testPeerID)
|
t.Error("removed peerID found", testPeerID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddSeeder(t *testing.T) {
|
func TestAddSeeder(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
|
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundSeeder, found := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, found := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if found && foundSeeder != *testSeeder {
|
if found && foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not added to cache", testSeeder)
|
t.Error("seeder not added to cache", testSeeder)
|
||||||
}
|
}
|
||||||
foundSeeder, found = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, found = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if found && foundSeeder != *testSeeder {
|
if found && foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not added to local", testSeeder)
|
t.Error("seeder not added to local", testSeeder)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddLeecher(t *testing.T) {
|
func TestAddLeecher(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
|
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found && foundLeecher != *testLeecher {
|
if found && foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not added to cache", testLeecher)
|
t.Error("leecher not added to cache", testLeecher)
|
||||||
}
|
}
|
||||||
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found && foundLeecher != *testLeecher {
|
if found && foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not added to local", testLeecher)
|
t.Error("leecher not added to local", testLeecher)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveSeeder(t *testing.T) {
|
func TestRemoveSeeder(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
|
|
||||||
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
||||||
foundSeeder, found := testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, found := testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if found || foundSeeder == *testSeeder {
|
if found || foundSeeder == *testSeeder {
|
||||||
t.Error("seeder not removed from local", foundSeeder)
|
t.Error("seeder not removed from local", foundSeeder)
|
||||||
}
|
}
|
||||||
|
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundSeeder, found = foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, found = foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if found || foundSeeder == *testSeeder {
|
if found || foundSeeder == *testSeeder {
|
||||||
t.Error("seeder not removed from cache", foundSeeder, *testSeeder)
|
t.Error("seeder not removed from cache", foundSeeder, *testSeeder)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveLeecher(t *testing.T) {
|
func TestRemoveLeecher(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
|
|
||||||
panicOnErr(conn.RemoveLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.RemoveLeecher(testTorrent, testLeecher))
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found || foundLeecher == *testLeecher {
|
if found || foundLeecher == *testLeecher {
|
||||||
t.Error("leecher not removed from cache", foundLeecher, *testLeecher)
|
t.Error("leecher not removed from cache", foundLeecher, *testLeecher)
|
||||||
}
|
}
|
||||||
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found || foundLeecher == *testLeecher {
|
if found || foundLeecher == *testLeecher {
|
||||||
t.Error("leecher not removed from local", foundLeecher, *testLeecher)
|
t.Error("leecher not removed from local", foundLeecher, *testLeecher)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetSeeder(t *testing.T) {
|
func TestSetSeeder(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
|
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
testSeeder.Uploaded += uint64(r.Int63())
|
testSeeder.Uploaded += uint64(r.Int63())
|
||||||
|
|
||||||
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
||||||
|
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if foundSeeder != *testSeeder {
|
if foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
|
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
|
||||||
}
|
}
|
||||||
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if foundSeeder != *testSeeder {
|
if foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
|
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetLeecher(t *testing.T) {
|
func TestSetLeecher(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
|
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
testLeecher.Uploaded += uint64(r.Int63())
|
testLeecher.Uploaded += uint64(r.Int63())
|
||||||
|
|
||||||
panicOnErr(conn.SetLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.SetLeecher(testTorrent, testLeecher))
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundLeecher, _ := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, _ := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if foundLeecher != *testLeecher {
|
if foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not updated in cache", testLeecher)
|
t.Error("leecher not updated in cache", testLeecher)
|
||||||
}
|
}
|
||||||
foundLeecher, _ = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, _ = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if foundLeecher != *testLeecher {
|
if foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not updated in local", testLeecher)
|
t.Error("leecher not updated in local", testLeecher)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIncrementSlots(t *testing.T) {
|
func TestIncrementSlots(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
numSlots := testUser.Slots
|
numSlots := testUser.Slots
|
||||||
|
|
||||||
panicOnErr(conn.IncrementSlots(testUser))
|
panicOnErr(conn.IncrementSlots(testUser))
|
||||||
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
if foundUser.Slots != numSlots+1 {
|
if foundUser.Slots != numSlots+1 {
|
||||||
t.Error("cached slots not incremented")
|
t.Error("cached slots not incremented")
|
||||||
}
|
}
|
||||||
if testUser.Slots != numSlots+1 {
|
if testUser.Slots != numSlots+1 {
|
||||||
t.Error("local slots not incremented")
|
t.Error("local slots not incremented")
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDecrementSlots(t *testing.T) {
|
func TestDecrementSlots(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
numSlots := testUser.Slots
|
numSlots := testUser.Slots
|
||||||
|
|
||||||
panicOnErr(conn.DecrementSlots(testUser))
|
panicOnErr(conn.DecrementSlots(testUser))
|
||||||
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
foundUser, _, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
if foundUser.Slots != numSlots-1 {
|
if foundUser.Slots != numSlots-1 {
|
||||||
t.Error("cached slots not incremented")
|
t.Error("cached slots not incremented")
|
||||||
}
|
}
|
||||||
if testUser.Slots != numSlots-1 {
|
if testUser.Slots != numSlots-1 {
|
||||||
t.Error("local slots not incremented")
|
t.Error("local slots not incremented")
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLeecherFinished(t *testing.T) {
|
func TestLeecherFinished(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
testLeecher.Left = 0
|
testLeecher.Left = 0
|
||||||
|
|
||||||
panicOnErr(conn.LeecherFinished(testTorrent, testLeecher))
|
panicOnErr(conn.LeecherFinished(testTorrent, testLeecher))
|
||||||
|
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testLeecher)]
|
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testLeecher)]
|
||||||
if foundSeeder != *testLeecher {
|
if foundSeeder != *testLeecher {
|
||||||
t.Error("seeder not added to cache", foundSeeder, *testLeecher)
|
t.Error("seeder not added to cache", foundSeeder, *testLeecher)
|
||||||
}
|
}
|
||||||
foundSeeder, _ = foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundSeeder, _ = foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if foundSeeder == *testLeecher {
|
if foundSeeder == *testLeecher {
|
||||||
t.Error("leecher not removed from cache", testLeecher)
|
t.Error("leecher not removed from cache", testLeecher)
|
||||||
}
|
}
|
||||||
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testLeecher)]
|
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testLeecher)]
|
||||||
if foundSeeder != *testLeecher {
|
if foundSeeder != *testLeecher {
|
||||||
t.Error("seeder not added to local", testLeecher)
|
t.Error("seeder not added to local", testLeecher)
|
||||||
}
|
}
|
||||||
foundSeeder, _ = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundSeeder, _ = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if foundSeeder == *testLeecher {
|
if foundSeeder == *testLeecher {
|
||||||
t.Error("leecher not removed from local", testLeecher)
|
t.Error("leecher not removed from local", testLeecher)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add, update, verify remove
|
// Add, update, verify remove
|
||||||
func TestUpdatePeer(t *testing.T) {
|
func TestUpdatePeer(t *testing.T) {
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
// Update a seeder, set it, then check to make sure it updated
|
// Update a seeder, set it, then check to make sure it updated
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
testSeeder.Uploaded += uint64(r.Int63())
|
testSeeder.Uploaded += uint64(r.Int63())
|
||||||
|
|
||||||
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
||||||
|
|
||||||
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if seeder, exists := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]; exists {
|
if seeder, exists := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]; exists {
|
||||||
t.Error("seeder not removed from cache", seeder)
|
t.Error("seeder not removed from cache", seeder)
|
||||||
}
|
}
|
||||||
if seeder, exists := testTorrent.Seeders[storage.PeerMapKey(testSeeder)]; exists {
|
if seeder, exists := testTorrent.Seeders[storage.PeerMapKey(testSeeder)]; exists {
|
||||||
t.Error("seeder not removed from local", seeder)
|
t.Error("seeder not removed from local", seeder)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelFindUser(t *testing.T) {
|
func TestParallelFindUser(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUserSuccess := createTestUser()
|
testUserSuccess := createTestUser()
|
||||||
testUserFail := createTestUser()
|
testUserFail := createTestUser()
|
||||||
panicOnErr(conn.AddUser(testUserSuccess))
|
panicOnErr(conn.AddUser(testUserSuccess))
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
foundUser, found, err := conn.FindUser(testUserFail.Passkey)
|
foundUser, found, err := conn.FindUser(testUserFail.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("user found", foundUser)
|
t.Error("user found", foundUser)
|
||||||
}
|
}
|
||||||
foundUser, found, err = conn.FindUser(testUserSuccess.Passkey)
|
foundUser, found, err = conn.FindUser(testUserSuccess.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("user not found", testUserSuccess)
|
t.Error("user not found", testUserSuccess)
|
||||||
}
|
}
|
||||||
if *foundUser != *testUserSuccess {
|
if *foundUser != *testUserSuccess {
|
||||||
t.Error("found user mismatch", *foundUser, testUserSuccess)
|
t.Error("found user mismatch", *foundUser, testUserSuccess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveUser(testUserSuccess))
|
panicOnErr(conn.RemoveUser(testUserSuccess))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelFindTorrent(t *testing.T) {
|
func TestParallelFindTorrent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrentSuccess := createTestTorrent()
|
testTorrentSuccess := createTestTorrent()
|
||||||
testTorrentFail := createTestTorrent()
|
testTorrentFail := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrentSuccess))
|
panicOnErr(conn.AddTorrent(testTorrentSuccess))
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrentSuccess.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrentSuccess.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
t.Error("torrent not found", testTorrentSuccess)
|
t.Error("torrent not found", testTorrentSuccess)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(foundTorrent, testTorrentSuccess) {
|
if !reflect.DeepEqual(foundTorrent, testTorrentSuccess) {
|
||||||
t.Error("found torrent mismatch", foundTorrent, testTorrentSuccess)
|
t.Error("found torrent mismatch", foundTorrent, testTorrentSuccess)
|
||||||
}
|
}
|
||||||
foundTorrent, found, err = conn.FindTorrent(testTorrentFail.Infohash)
|
foundTorrent, found, err = conn.FindTorrent(testTorrentFail.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
t.Error("torrent found", foundTorrent)
|
t.Error("torrent found", foundTorrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrentSuccess))
|
panicOnErr(conn.RemoveTorrent(testTorrentSuccess))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelSetSeeder(t *testing.T) {
|
func TestParallelSetSeeder(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
testSeeder.Uploaded += uint64(r.Int63())
|
testSeeder.Uploaded += uint64(r.Int63())
|
||||||
|
|
||||||
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.SetSeeder(testTorrent, testSeeder))
|
||||||
|
|
||||||
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, _, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, _ := foundTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if foundSeeder != *testSeeder {
|
if foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
|
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
|
||||||
}
|
}
|
||||||
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
foundSeeder, _ = testTorrent.Seeders[storage.PeerMapKey(testSeeder)]
|
||||||
if foundSeeder != *testSeeder {
|
if foundSeeder != *testSeeder {
|
||||||
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
|
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelAddLeecher(t *testing.T) {
|
func TestParallelAddLeecher(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
|
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
|
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found := foundTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found && foundLeecher != *testLeecher {
|
if found && foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not added to cache", testLeecher)
|
t.Error("leecher not added to cache", testLeecher)
|
||||||
}
|
}
|
||||||
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
foundLeecher, found = testTorrent.Leechers[storage.PeerMapKey(testLeecher)]
|
||||||
if found && foundLeecher != *testLeecher {
|
if found && foundLeecher != *testLeecher {
|
||||||
t.Error("leecher not added to local", testLeecher)
|
t.Error("leecher not added to local", testLeecher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,284 +5,284 @@
|
||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkSuccessfulFindUser(b *testing.B) {
|
func BenchmarkSuccessfulFindUser(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
|
|
||||||
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
foundUser, found, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
b.Error("user not found", testUser)
|
b.Error("user not found", testUser)
|
||||||
}
|
}
|
||||||
if *foundUser != *testUser {
|
if *foundUser != *testUser {
|
||||||
b.Error("found user mismatch", *foundUser, testUser)
|
b.Error("found user mismatch", *foundUser, testUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkFailedFindUser(b *testing.B) {
|
func BenchmarkFailedFindUser(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
|
|
||||||
_, found, err := conn.FindUser(testUser.Passkey)
|
_, found, err := conn.FindUser(testUser.Passkey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
b.Error("user not found", testUser)
|
b.Error("user not found", testUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSuccessfulFindTorrent(b *testing.B) {
|
func BenchmarkSuccessfulFindTorrent(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
|
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
b.Error("torrent not found", testTorrent)
|
b.Error("torrent not found", testTorrent)
|
||||||
}
|
}
|
||||||
// Incomplete comparison as maps make struct not nativly comparable
|
// Incomplete comparison as maps make struct not nativly comparable
|
||||||
if foundTorrent.Infohash != testTorrent.Infohash {
|
if foundTorrent.Infohash != testTorrent.Infohash {
|
||||||
b.Error("found torrent mismatch", foundTorrent, testTorrent)
|
b.Error("found torrent mismatch", foundTorrent, testTorrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkFailFindTorrent(b *testing.B) {
|
func BenchmarkFailFindTorrent(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
foundTorrent, found, err := conn.FindTorrent(testTorrent.Infohash)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
b.Error("torrent found", foundTorrent)
|
b.Error("torrent found", foundTorrent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSuccessfulClientWhitelisted(b *testing.B) {
|
func BenchmarkSuccessfulClientWhitelisted(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testPeerID := "-lt0D30-"
|
testPeerID := "-lt0D30-"
|
||||||
panicOnErr(conn.WhitelistClient(testPeerID))
|
panicOnErr(conn.WhitelistClient(testPeerID))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
found, err := conn.ClientWhitelisted(testPeerID)
|
found, err := conn.ClientWhitelisted(testPeerID)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if !found {
|
if !found {
|
||||||
b.Error("peerID not found", testPeerID)
|
b.Error("peerID not found", testPeerID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
panicOnErr(conn.UnWhitelistClient(testPeerID))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkFailClientWhitelisted(b *testing.B) {
|
func BenchmarkFailClientWhitelisted(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testPeerID2 := "TIX0192"
|
testPeerID2 := "TIX0192"
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
found, err := conn.ClientWhitelisted(testPeerID2)
|
found, err := conn.ClientWhitelisted(testPeerID2)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if found {
|
if found {
|
||||||
b.Error("peerID found", testPeerID2)
|
b.Error("peerID found", testPeerID2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRecordSnatch(b *testing.B) {
|
func BenchmarkRecordSnatch(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
panicOnErr(conn.RecordSnatch(testUser, testTorrent))
|
panicOnErr(conn.RecordSnatch(testUser, testTorrent))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMarkActive(b *testing.B) {
|
func BenchmarkMarkActive(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
testTorrent.Active = false
|
testTorrent.Active = false
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
panicOnErr(conn.MarkActive(testTorrent))
|
panicOnErr(conn.MarkActive(testTorrent))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAddSeeder(b *testing.B) {
|
func BenchmarkAddSeeder(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRemoveSeeder(b *testing.B) {
|
func BenchmarkRemoveSeeder(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn.AddSeeder(testTorrent, testSeeder)
|
conn.AddSeeder(testTorrent, testSeeder)
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.RemoveSeeder(testTorrent, testSeeder))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSetSeeder(b *testing.B) {
|
func BenchmarkSetSeeder(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
panicOnErr(conn.AddSeeder(testTorrent, testSeeder))
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
testSeeder.Uploaded += uint64(r.Int63())
|
testSeeder.Uploaded += uint64(r.Int63())
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
conn.SetSeeder(testTorrent, testSeeder)
|
conn.SetSeeder(testTorrent, testSeeder)
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkIncrementSlots(b *testing.B) {
|
func BenchmarkIncrementSlots(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testUser := createTestUser()
|
testUser := createTestUser()
|
||||||
panicOnErr(conn.AddUser(testUser))
|
panicOnErr(conn.AddUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
panicOnErr(conn.IncrementSlots(testUser))
|
panicOnErr(conn.IncrementSlots(testUser))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveUser(testUser))
|
panicOnErr(conn.RemoveUser(testUser))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLeecherFinished(b *testing.B) {
|
func BenchmarkLeecherFinished(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
testLeecher.Left = 0
|
testLeecher.Left = 0
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
panicOnErr(conn.LeecherFinished(testTorrent, testLeecher))
|
panicOnErr(conn.LeecherFinished(testTorrent, testLeecher))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
panicOnErr(conn.RemoveTorrent(testTorrent))
|
panicOnErr(conn.RemoveTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a comparision to the Leecher finished function
|
// This is a comparision to the Leecher finished function
|
||||||
func BenchmarkRemoveLeecherAddSeeder(b *testing.B) {
|
func BenchmarkRemoveLeecherAddSeeder(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn := createTestConn()
|
conn := createTestConn()
|
||||||
testTorrent := createTestTorrent()
|
testTorrent := createTestTorrent()
|
||||||
panicOnErr(conn.AddTorrent(testTorrent))
|
panicOnErr(conn.AddTorrent(testTorrent))
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for bCount := 0; bCount < b.N; bCount++ {
|
for bCount := 0; bCount < b.N; bCount++ {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||||
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.AddLeecher(testTorrent, testLeecher))
|
||||||
testLeecher.Left = 0
|
testLeecher.Left = 0
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
panicOnErr(conn.RemoveLeecher(testTorrent, testLeecher))
|
panicOnErr(conn.RemoveLeecher(testTorrent, testLeecher))
|
||||||
panicOnErr(conn.AddSeeder(testTorrent, testLeecher))
|
panicOnErr(conn.AddSeeder(testTorrent, testLeecher))
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
conn.RemoveTorrent(testTorrent)
|
conn.RemoveTorrent(testTorrent)
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,180 +5,180 @@
|
||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/garyburd/redigo/redis"
|
"github.com/garyburd/redigo/redis"
|
||||||
|
|
||||||
"github.com/pushrax/chihaya/config"
|
"github.com/pushrax/chihaya/config"
|
||||||
"github.com/pushrax/chihaya/storage"
|
"github.com/pushrax/chihaya/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testTorrentIDChannel chan uint64
|
testTorrentIDChannel chan uint64
|
||||||
testUserIDChannel chan uint64
|
testUserIDChannel chan uint64
|
||||||
testPeerIDChannel chan int
|
testPeerIDChannel chan int
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
testTorrentIDChannel = make(chan uint64, 100)
|
testTorrentIDChannel = make(chan uint64, 100)
|
||||||
testUserIDChannel = make(chan uint64, 100)
|
testUserIDChannel = make(chan uint64, 100)
|
||||||
testPeerIDChannel = make(chan int, 100)
|
testPeerIDChannel = make(chan int, 100)
|
||||||
// Sync access to ID counter with buffered global channels
|
// Sync access to ID counter with buffered global channels
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
testTorrentIDChannel <- uint64(i)
|
testTorrentIDChannel <- uint64(i)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
testUserIDChannel <- uint64(i)
|
testUserIDChannel <- uint64(i)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
testPeerIDChannel <- i
|
testPeerIDChannel <- i
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestTorrentID() uint64 {
|
func createTestTorrentID() uint64 {
|
||||||
return <-testTorrentIDChannel
|
return <-testTorrentIDChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestUserID() uint64 {
|
func createTestUserID() uint64 {
|
||||||
return <-testUserIDChannel
|
return <-testUserIDChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestPeerID() string {
|
func createTestPeerID() string {
|
||||||
return "-testPeerID-" + strconv.Itoa(<-testPeerIDChannel)
|
return "-testPeerID-" + strconv.Itoa(<-testPeerIDChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestInfohash() string {
|
func createTestInfohash() string {
|
||||||
uuid := make([]byte, 40)
|
uuid := make([]byte, 40)
|
||||||
n, err := io.ReadFull(rand.Reader, uuid)
|
n, err := io.ReadFull(rand.Reader, uuid)
|
||||||
if n != len(uuid) || err != nil {
|
if n != len(uuid) || err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return string(uuid)
|
return string(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestPasskey() string {
|
func createTestPasskey() string {
|
||||||
uuid := make([]byte, 40)
|
uuid := make([]byte, 40)
|
||||||
n, err := io.ReadFull(rand.Reader, uuid)
|
n, err := io.ReadFull(rand.Reader, uuid)
|
||||||
if n != len(uuid) || err != nil {
|
if n != len(uuid) || err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return string(uuid)
|
return string(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func panicOnErr(err error) {
|
func panicOnErr(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestRedisConn() *Conn {
|
func createTestRedisConn() *Conn {
|
||||||
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
||||||
conf := &testConfig.Cache
|
conf := &testConfig.Cache
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
testPool := &Pool{
|
testPool := &Pool{
|
||||||
conf: conf,
|
conf: conf,
|
||||||
pool: redis.Pool{
|
pool: redis.Pool{
|
||||||
MaxIdle: conf.MaxIdleConns,
|
MaxIdle: conf.MaxIdleConns,
|
||||||
IdleTimeout: conf.IdleTimeout.Duration,
|
IdleTimeout: conf.IdleTimeout.Duration,
|
||||||
Dial: makeDialFunc(conf),
|
Dial: makeDialFunc(conf),
|
||||||
TestOnBorrow: testOnBorrow,
|
TestOnBorrow: testOnBorrow,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
newConn := &Conn{
|
newConn := &Conn{
|
||||||
conf: testPool.conf,
|
conf: testPool.conf,
|
||||||
done: false,
|
done: false,
|
||||||
Conn: testPool.pool.Get(),
|
Conn: testPool.pool.Get(),
|
||||||
}
|
}
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
// Test connection before returning
|
// Test connection before returning
|
||||||
_, err = newConn.Do("PING")
|
_, err = newConn.Do("PING")
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
return newConn
|
return newConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestUser() *storage.User {
|
func createTestUser() *storage.User {
|
||||||
return &storage.User{ID: createTestUserID(), Passkey: createTestPasskey(),
|
return &storage.User{ID: createTestUserID(), Passkey: createTestPasskey(),
|
||||||
UpMultiplier: 1.01, DownMultiplier: 1.0, Slots: 4, SlotsUsed: 2, Snatches: 7}
|
UpMultiplier: 1.01, DownMultiplier: 1.0, Slots: 4, SlotsUsed: 2, Snatches: 7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestPeer(userID uint64, torrentID uint64) *storage.Peer {
|
func createTestPeer(userID uint64, torrentID uint64) *storage.Peer {
|
||||||
|
|
||||||
return &storage.Peer{ID: createTestPeerID(), UserID: userID, TorrentID: torrentID,
|
return &storage.Peer{ID: createTestPeerID(), UserID: userID, TorrentID: torrentID,
|
||||||
IP: "127.0.0.1", Port: 6889, Uploaded: 1024, Downloaded: 3000, Left: 4200, LastAnnounce: 11}
|
IP: "127.0.0.1", Port: 6889, Uploaded: 1024, Downloaded: 3000, Left: 4200, LastAnnounce: 11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestPeers(torrentID uint64, num int) map[string]storage.Peer {
|
func createTestPeers(torrentID uint64, num int) map[string]storage.Peer {
|
||||||
testPeers := make(map[string]storage.Peer)
|
testPeers := make(map[string]storage.Peer)
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
tempPeer := createTestPeer(createTestUserID(), torrentID)
|
tempPeer := createTestPeer(createTestUserID(), torrentID)
|
||||||
testPeers[storage.PeerMapKey(tempPeer)] = *tempPeer
|
testPeers[storage.PeerMapKey(tempPeer)] = *tempPeer
|
||||||
}
|
}
|
||||||
return testPeers
|
return testPeers
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestTorrent() *storage.Torrent {
|
func createTestTorrent() *storage.Torrent {
|
||||||
|
|
||||||
torrentInfohash := createTestInfohash()
|
torrentInfohash := createTestInfohash()
|
||||||
torrentID := createTestTorrentID()
|
torrentID := createTestTorrentID()
|
||||||
|
|
||||||
testSeeders := createTestPeers(torrentID, 4)
|
testSeeders := createTestPeers(torrentID, 4)
|
||||||
testLeechers := createTestPeers(torrentID, 2)
|
testLeechers := createTestPeers(torrentID, 2)
|
||||||
|
|
||||||
testTorrent := storage.Torrent{ID: torrentID, Infohash: torrentInfohash, Active: true,
|
testTorrent := storage.Torrent{ID: torrentID, Infohash: torrentInfohash, Active: true,
|
||||||
Seeders: testSeeders, Leechers: testLeechers, Snatches: 11, UpMultiplier: 1.0, DownMultiplier: 1.0, LastAction: 0}
|
Seeders: testSeeders, Leechers: testLeechers, Snatches: 11, UpMultiplier: 1.0, DownMultiplier: 1.0, LastAction: 0}
|
||||||
return &testTorrent
|
return &testTorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidPeers(t *testing.T) {
|
func TestValidPeers(t *testing.T) {
|
||||||
testConn := createTestRedisConn()
|
testConn := createTestRedisConn()
|
||||||
testTorrentID := createTestTorrentID()
|
testTorrentID := createTestTorrentID()
|
||||||
testPeers := createTestPeers(testTorrentID, 3)
|
testPeers := createTestPeers(testTorrentID, 3)
|
||||||
|
|
||||||
panicOnErr(testConn.addPeers(testPeers, "test:"))
|
panicOnErr(testConn.addPeers(testPeers, "test:"))
|
||||||
peerMap, err := testConn.getPeers(testTorrentID, "test:")
|
peerMap, err := testConn.getPeers(testTorrentID, "test:")
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
if len(peerMap) != len(testPeers) {
|
if len(peerMap) != len(testPeers) {
|
||||||
t.Error("Num Peers not equal ", len(peerMap), len(testPeers))
|
t.Error("Num Peers not equal ", len(peerMap), len(testPeers))
|
||||||
}
|
}
|
||||||
panicOnErr(testConn.removePeers(testTorrentID, testPeers, "test:"))
|
panicOnErr(testConn.removePeers(testTorrentID, testPeers, "test:"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidPeers(t *testing.T) {
|
func TestInvalidPeers(t *testing.T) {
|
||||||
testConn := createTestRedisConn()
|
testConn := createTestRedisConn()
|
||||||
testTorrentID := createTestTorrentID()
|
testTorrentID := createTestTorrentID()
|
||||||
testPeers := createTestPeers(testTorrentID, 3)
|
testPeers := createTestPeers(testTorrentID, 3)
|
||||||
tempPeer := createTestPeer(createTestUserID(), testTorrentID)
|
tempPeer := createTestPeer(createTestUserID(), testTorrentID)
|
||||||
testPeers[storage.PeerMapKey(tempPeer)] = *tempPeer
|
testPeers[storage.PeerMapKey(tempPeer)] = *tempPeer
|
||||||
|
|
||||||
panicOnErr(testConn.addPeers(testPeers, "test:"))
|
panicOnErr(testConn.addPeers(testPeers, "test:"))
|
||||||
// Imitate a peer being removed during get
|
// Imitate a peer being removed during get
|
||||||
hashKey := testConn.conf.Prefix + getPeerHashKey(tempPeer)
|
hashKey := testConn.conf.Prefix + getPeerHashKey(tempPeer)
|
||||||
_, err := testConn.Do("DEL", hashKey)
|
_, err := testConn.Do("DEL", hashKey)
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
|
|
||||||
peerMap, err := testConn.getPeers(testTorrentID, "test:")
|
peerMap, err := testConn.getPeers(testTorrentID, "test:")
|
||||||
panicOnErr(err)
|
panicOnErr(err)
|
||||||
// Expect 1 less peer due to delete
|
// Expect 1 less peer due to delete
|
||||||
if len(peerMap) != len(testPeers)-1 {
|
if len(peerMap) != len(testPeers)-1 {
|
||||||
t.Error("Num Peers not equal ", len(peerMap), len(testPeers)-1)
|
t.Error("Num Peers not equal ", len(peerMap), len(testPeers)-1)
|
||||||
}
|
}
|
||||||
panicOnErr(testConn.removePeers(testTorrentID, testPeers, "test:"))
|
panicOnErr(testConn.removePeers(testTorrentID, testPeers, "test:"))
|
||||||
if len(testPeers) != 0 {
|
if len(testPeers) != 0 {
|
||||||
t.Errorf("All peers not removed, %d peers remain!", len(testPeers))
|
t.Errorf("All peers not removed, %d peers remain!", len(testPeers))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue