Completed cache.Tx tests and added benchmarks
This commit is contained in:
parent
3caa06b5f6
commit
1ea24f80dc
6 changed files with 527 additions and 323 deletions
67
cache/redis/redis.go
vendored
67
cache/redis/redis.go
vendored
|
@ -89,9 +89,8 @@ func (p *Pool) Get() (cache.Tx, error) {
|
|||
}
|
||||
|
||||
type Tx struct {
|
||||
conf *config.DataStore
|
||||
done bool
|
||||
multi bool
|
||||
conf *config.DataStore
|
||||
done bool
|
||||
redis.Conn
|
||||
}
|
||||
|
||||
|
@ -107,7 +106,6 @@ func createUser(userVals []string) (*models.User, error) {
|
|||
if len(userVals) != 7 {
|
||||
return nil, ErrCreateUser
|
||||
}
|
||||
// This could be a loop+switch
|
||||
ID, err := strconv.ParseUint(userVals[0], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -133,7 +131,8 @@ func createUser(userVals []string) (*models.User, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &models.User{ID, Passkey, UpMultiplier, DownMultiplier, Slots, SlotsUsed, uint(Snatches)}, nil
|
||||
return &models.User{ID: ID, Passkey: Passkey, UpMultiplier: UpMultiplier,
|
||||
DownMultiplier: DownMultiplier, Slots: Slots, SlotsUsed: SlotsUsed, Snatches: uint(Snatches)}, nil
|
||||
}
|
||||
|
||||
// This is a mulple action command, it's not internally atomic
|
||||
|
@ -175,7 +174,8 @@ func (tx *Tx) createTorrent(torrentVals []string) (*models.Torrent, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &models.Torrent{ID, Infohash, Active, seeders, leechers, uint(Snatches), UpMultiplier, DownMultiplier, LastAction}, nil
|
||||
return &models.Torrent{ID: ID, Infohash: Infohash, Active: Active, Seeders: seeders, Leechers: leechers,
|
||||
Snatches: uint(Snatches), UpMultiplier: UpMultiplier, DownMultiplier: DownMultiplier, LastAction: LastAction}, nil
|
||||
}
|
||||
|
||||
// The peer hashkey relies on the combination of peerID, userID, and torrentID being unique
|
||||
|
@ -220,7 +220,7 @@ func (tx *Tx) removePeers(torrentID uint64, peers map[string]models.Peer, peerTy
|
|||
}
|
||||
delete(peers, peer.ID)
|
||||
}
|
||||
// Only delete the set if all the peer deletions were successful
|
||||
// Will only delete the set if all the peer deletions were successful
|
||||
setKey := tx.conf.Prefix + peerTypePrefix + strconv.FormatUint(torrentID, 36)
|
||||
_, err := tx.Do("DEL", setKey)
|
||||
if err != nil {
|
||||
|
@ -234,8 +234,8 @@ func getPeerHashKey(peer *models.Peer) string {
|
|||
return peer.ID + ":" + strconv.FormatUint(peer.UserID, 36) + ":" + strconv.FormatUint(peer.TorrentID, 36)
|
||||
}
|
||||
|
||||
func getPeerSetKey(prefix string, peer *models.Peer) string {
|
||||
return prefix + strconv.FormatUint(peer.TorrentID, 36)
|
||||
func getPeerSetKey(typePrefix string, peer *models.Peer) string {
|
||||
return typePrefix + strconv.FormatUint(peer.TorrentID, 36)
|
||||
}
|
||||
|
||||
// This is a mulple action command, it's not internally atomic
|
||||
|
@ -286,7 +286,8 @@ func createPeer(peerVals []string) (*models.Peer, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &models.Peer{ID, UserID, TorrentID, IP, Port, Uploaded, Downloaded, Left, LastAnnounce}, nil
|
||||
return &models.Peer{ID: ID, UserID: UserID, TorrentID: TorrentID, IP: IP, Port: Port,
|
||||
Uploaded: Uploaded, Downloaded: Downloaded, Left: Left, LastAnnounce: LastAnnounce}, nil
|
||||
|
||||
}
|
||||
|
||||
|
@ -309,7 +310,7 @@ func (tx *Tx) getPeers(torrentID uint64, peerTypePrefix string) (peers map[strin
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
peers[peer.ID] = *peer
|
||||
peers[models.PeerMapKey(peer)] = *peer
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -356,7 +357,6 @@ func (tx *Tx) RemoveTorrent(t *models.Torrent) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -438,14 +438,14 @@ func (tx *Tx) UnWhitelistClient(peerID string) error {
|
|||
func (tx *Tx) RecordSnatch(user *models.User, torrent *models.Torrent) error {
|
||||
|
||||
torrentKey := tx.conf.Prefix + TorrentPrefix + torrent.Infohash
|
||||
snatchCount, err := redis.Int(tx.Do("HINCRBY", torrentKey, 1))
|
||||
snatchCount, err := redis.Int(tx.Do("HINCRBY", torrentKey, "snatches", 1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
torrent.Snatches = uint(snatchCount)
|
||||
|
||||
userKey := tx.conf.Prefix + TorrentPrefix + torrent.Infohash
|
||||
snatchCount, err = redis.Int(tx.Do("HINCRBY", userKey, 1))
|
||||
userKey := tx.conf.Prefix + UserPrefix + user.Passkey
|
||||
snatchCount, err = redis.Int(tx.Do("HINCRBY", userKey, "snatches", 1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -455,10 +455,25 @@ func (tx *Tx) RecordSnatch(user *models.User, torrent *models.Torrent) error {
|
|||
|
||||
func (tx *Tx) MarkActive(torrent *models.Torrent) error {
|
||||
hashkey := tx.conf.Prefix + TorrentPrefix + torrent.Infohash
|
||||
activeExists, err := redis.Int(tx.Do("HSET", hashkey, true))
|
||||
activeExists, err := redis.Int(tx.Do("HSET", hashkey, "active", true))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
torrent.Active = true
|
||||
// HSET returns 1 if hash didn't exist before
|
||||
if activeExists == 1 {
|
||||
return ErrMarkActive
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) MarkInActive(torrent *models.Torrent) error {
|
||||
hashkey := tx.conf.Prefix + TorrentPrefix + torrent.Infohash
|
||||
activeExists, err := redis.Int(tx.Do("HSET", hashkey, "active", false))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
torrent.Active = false
|
||||
// HSET returns 1 if hash didn't exist before
|
||||
if activeExists == 1 {
|
||||
return ErrMarkActive
|
||||
|
@ -480,7 +495,7 @@ func (tx *Tx) AddLeecher(torrent *models.Torrent, peer *models.Peer) error {
|
|||
if torrent.Leechers == nil {
|
||||
torrent.Leechers = make(map[string]models.Peer)
|
||||
}
|
||||
torrent.Leechers[peer.ID] = *peer
|
||||
torrent.Leechers[models.PeerMapKey(peer)] = *peer
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -491,7 +506,7 @@ func (tx *Tx) SetLeecher(t *models.Torrent, p *models.Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.Leechers[p.ID] = *p
|
||||
t.Leechers[models.PeerMapKey(p)] = *p
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -500,7 +515,7 @@ func (tx *Tx) RemoveLeecher(t *models.Torrent, p *models.Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(t.Leechers, p.ID)
|
||||
delete(t.Leechers, models.PeerMapKey(p))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -513,8 +528,8 @@ func (tx *Tx) LeecherFinished(torrent *models.Torrent, peer *models.Peer) error
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
torrent.Seeders[peer.ID] = *peer
|
||||
delete(torrent.Leechers, peer.ID)
|
||||
torrent.Seeders[models.PeerMapKey(peer)] = *peer
|
||||
delete(torrent.Leechers, models.PeerMapKey(peer))
|
||||
|
||||
err = tx.setPeer(peer)
|
||||
return err
|
||||
|
@ -534,7 +549,7 @@ func (tx *Tx) AddSeeder(torrent *models.Torrent, peer *models.Peer) error {
|
|||
if torrent.Seeders == nil {
|
||||
torrent.Seeders = make(map[string]models.Peer)
|
||||
}
|
||||
torrent.Seeders[peer.ID] = *peer
|
||||
torrent.Seeders[models.PeerMapKey(peer)] = *peer
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -543,7 +558,7 @@ func (tx *Tx) SetSeeder(t *models.Torrent, p *models.Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.Seeders[p.ID] = *p
|
||||
t.Seeders[models.PeerMapKey(p)] = *p
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -552,13 +567,13 @@ func (tx *Tx) RemoveSeeder(t *models.Torrent, p *models.Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(t.Seeders, p.ID)
|
||||
delete(t.Seeders, models.PeerMapKey(p))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) IncrementSlots(u *models.User) error {
|
||||
hashkey := tx.conf.Prefix + UserPrefix + u.Passkey
|
||||
slotCount, err := redis.Int(tx.Do("HINCRBY", hashkey, 1))
|
||||
slotCount, err := redis.Int(tx.Do("HINCRBY", hashkey, "slots", 1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -568,7 +583,7 @@ func (tx *Tx) IncrementSlots(u *models.User) error {
|
|||
|
||||
func (tx *Tx) DecrementSlots(u *models.User) error {
|
||||
hashkey := tx.conf.Prefix + UserPrefix + u.Passkey
|
||||
slotCount, err := redis.Int(tx.Do("HINCRBY", hashkey, -1))
|
||||
slotCount, err := redis.Int(tx.Do("HINCRBY", hashkey, "slots", -1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
336
cache/redis/redis_bench_test.go
vendored
336
cache/redis/redis_bench_test.go
vendored
|
@ -6,128 +6,240 @@
|
|||
package redis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
|
||||
"github.com/pushrax/chihaya/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTxDone = errors.New("cache: Transaction has already been committed or rolled back")
|
||||
ErrTxConflict = errors.New("cache: Commit interrupted, update transaction and repeat")
|
||||
)
|
||||
|
||||
// Maximum number of parallel retries; depends on system latency
|
||||
const MAX_RETRIES = 9000
|
||||
|
||||
// Legacy JSON support for benching
|
||||
func (tx *Tx) initiateWrite() error {
|
||||
if tx.done {
|
||||
return ErrTxDone
|
||||
}
|
||||
if tx.multi != true {
|
||||
tx.multi = true
|
||||
return tx.Send("MULTI")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) initiateRead() error {
|
||||
if tx.done {
|
||||
return ErrTxDone
|
||||
}
|
||||
if tx.multi == true {
|
||||
panic("Tried to read during MULTI")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) Commit() error {
|
||||
if tx.done {
|
||||
return ErrTxDone
|
||||
}
|
||||
if tx.multi == true {
|
||||
execResponse, err := tx.Do("EXEC")
|
||||
if execResponse == nil {
|
||||
tx.multi = false
|
||||
return ErrTxConflict
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
tx.close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) Rollback() error {
|
||||
if tx.done {
|
||||
return ErrTxDone
|
||||
}
|
||||
// Undoes watches and multi
|
||||
if _, err := tx.Do("DISCARD"); err != nil {
|
||||
return err
|
||||
}
|
||||
tx.multi = false
|
||||
tx.close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExampleRedisTypesSchemaFindUser(passkey string, t TestReporter) (*models.User, bool) {
|
||||
testTx := createTestTxObj(t)
|
||||
hashkey := testTx.conf.Prefix + UserPrefix + passkey
|
||||
userVals, err := redis.Strings(testTx.Do("HVALS", hashkey))
|
||||
if len(userVals) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
verifyErrNil(err, t)
|
||||
compareUser, err := createUser(userVals)
|
||||
verifyErrNil(err, t)
|
||||
return compareUser, true
|
||||
}
|
||||
|
||||
func BenchmarkRedisTypesSchemaRemoveSeeder(b *testing.B) {
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
//TODO this needs to be updated
|
||||
b.Error("Unimplemented")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRedisTypesSchemaFindUser(b *testing.B) {
|
||||
|
||||
// Ensure successful user find ( a failed lookup may have different performance )
|
||||
func BenchmarkSuccessfulFindUser(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testUser := createTestUser()
|
||||
testTx := createTestTxObj(b)
|
||||
hashkey := testTx.conf.Prefix + UserPrefix + testUser.Passkey
|
||||
reply, err := testTx.Do("HMSET", hashkey,
|
||||
"id", testUser.ID,
|
||||
"passkey", testUser.Passkey,
|
||||
"up_multiplier", testUser.UpMultiplier,
|
||||
"down_multiplier", testUser.DownMultiplier,
|
||||
"slots", testUser.Slots,
|
||||
"slots_used", testUser.SlotsUsed)
|
||||
|
||||
if reply == nil {
|
||||
b.Log("no hash fields added!")
|
||||
}
|
||||
verifyErrNil(err, b)
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
|
||||
compareUser, exists := ExampleRedisTypesSchemaFindUser(testUser.Passkey, b)
|
||||
|
||||
b.StopTimer()
|
||||
if !exists {
|
||||
b.Error("User not found!")
|
||||
foundUser, found, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
b.Error("user not found", testUser)
|
||||
}
|
||||
if testUser != *compareUser {
|
||||
b.Errorf("user mismatch: %v vs. %v", compareUser, testUser)
|
||||
if *foundUser != *testUser {
|
||||
b.Error("found user mismatch", *foundUser, testUser)
|
||||
}
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFailedFindUser(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testUser := createTestUser()
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
|
||||
_, found, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
b.Error("user not found", testUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSuccessfulFindTorrent(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
b.Error("torrent not found", testTorrent)
|
||||
}
|
||||
// Incomplete comparison as maps make struct not nativly comparable
|
||||
if foundTorrent.Infohash != testTorrent.Infohash {
|
||||
b.Error("found torrent mismatch", foundTorrent, testTorrent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFailFindTorrent(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
b.Error("torrent found", foundTorrent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSuccessfulClientWhitelisted(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testPeerID := "-lt0D30-"
|
||||
panicErrNil(tx.WhitelistClient(testPeerID))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
found, err := tx.ClientWhitelisted(testPeerID)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
b.Error("peerID not found", testPeerID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFailClientWhitelisted(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testPeerID2 := "TIX0192"
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
found, err := tx.ClientWhitelisted(testPeerID2)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
b.Error("peerID found", testPeerID2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRecordSnatch(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
testUser := createTestUser()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
panicErrNil(tx.RecordSnatch(testUser, testTorrent))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarkActive(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
testTorrent.Active = false
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
panicErrNil(tx.MarkActive(testTorrent))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAddSeeder(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
b.StopTimer()
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
b.StartTimer()
|
||||
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRemoveSeeder(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
b.StopTimer()
|
||||
tx.AddSeeder(testTorrent, testSeeder)
|
||||
b.StartTimer()
|
||||
|
||||
panicErrNil(tx.RemoveSeeder(testTorrent, testSeeder))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSetSeeder(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
b.StopTimer()
|
||||
testSeeder.Uploaded += uint64(r.Int63())
|
||||
b.StartTimer()
|
||||
|
||||
tx.SetSeeder(testTorrent, testSeeder)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIncrementSlots(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testUser := createTestUser()
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
panicErrNil(tx.IncrementSlots(testUser))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLeecherFinished(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
b.StopTimer()
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
testLeecher.Left = 0
|
||||
b.StartTimer()
|
||||
|
||||
panicErrNil(tx.LeecherFinished(testTorrent, testLeecher))
|
||||
}
|
||||
}
|
||||
|
||||
// This is a comparision to the Leecher finished function
|
||||
func BenchmarkRemoveLeecherAddSeeder(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
b.StartTimer()
|
||||
|
||||
for bCount := 0; bCount < b.N; bCount++ {
|
||||
b.StopTimer()
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
testLeecher.Left = 0
|
||||
b.StartTimer()
|
||||
|
||||
panicErrNil(tx.RemoveLeecher(testTorrent, testLeecher))
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testLeecher))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
68
cache/redis/redis_test.go
vendored
68
cache/redis/redis_test.go
vendored
|
@ -6,6 +6,7 @@ package redis
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
@ -64,16 +65,17 @@ type TestReporter interface {
|
|||
Logf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
func verifyErrNil(err error, t TestReporter) {
|
||||
func panicErrNil(err error) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
fmt.Println(err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func createTestTxObj(t TestReporter) *Tx {
|
||||
func createTestTxObj() *Tx {
|
||||
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
||||
conf := &testConfig.Cache
|
||||
verifyErrNil(err, t)
|
||||
panicErrNil(err)
|
||||
|
||||
testPool := &Pool{
|
||||
conf: conf,
|
||||
|
@ -86,27 +88,27 @@ func createTestTxObj(t TestReporter) *Tx {
|
|||
}
|
||||
|
||||
txObj := &Tx{
|
||||
conf: testPool.conf,
|
||||
done: false,
|
||||
multi: false,
|
||||
Conn: testPool.pool.Get(),
|
||||
conf: testPool.conf,
|
||||
done: false,
|
||||
Conn: testPool.pool.Get(),
|
||||
}
|
||||
verifyErrNil(err, t)
|
||||
panicErrNil(err)
|
||||
|
||||
// Test connection before returning
|
||||
_, err = txObj.Do("PING")
|
||||
verifyErrNil(err, t)
|
||||
panicErrNil(err)
|
||||
return txObj
|
||||
}
|
||||
|
||||
func createTestUser() models.User {
|
||||
testUser := models.User{createTestUserID(), createTestPasskey(), 1.01, 1.0, 4, 2, 7}
|
||||
return testUser
|
||||
func createTestUser() *models.User {
|
||||
return &models.User{ID: createTestUserID(), Passkey: createTestPasskey(),
|
||||
UpMultiplier: 1.01, DownMultiplier: 1.0, Slots: 4, SlotsUsed: 2, Snatches: 7}
|
||||
}
|
||||
|
||||
func createTestPeer(userID uint64, torrentID uint64) *models.Peer {
|
||||
|
||||
return &models.Peer{createTestPeerID(), userID, torrentID, "127.0.0.1", 6889, 1024, 3000, 4200, 11}
|
||||
return &models.Peer{ID: createTestPeerID(), UserID: userID, TorrentID: torrentID,
|
||||
IP: "127.0.0.1", Port: 6889, Uploaded: 1024, Downloaded: 3000, Left: 4200, LastAnnounce: 11}
|
||||
}
|
||||
|
||||
func createTestPeers(torrentID uint64, num int) map[string]models.Peer {
|
||||
|
@ -126,36 +128,22 @@ func createTestTorrent() *models.Torrent {
|
|||
testSeeders := createTestPeers(torrentID, 4)
|
||||
testLeechers := createTestPeers(torrentID, 2)
|
||||
|
||||
testTorrent := models.Torrent{torrentID, torrentInfohash, true, testSeeders, testLeechers, 11, 0.0, 0.0, 0}
|
||||
testTorrent := models.Torrent{ID: torrentID, Infohash: torrentInfohash, Active: true,
|
||||
Seeders: testSeeders, Leechers: testLeechers, Snatches: 11, UpMultiplier: 1.0, DownMultiplier: 1.0, LastAction: 0}
|
||||
return &testTorrent
|
||||
}
|
||||
|
||||
func TestAddGetPeers(t *testing.T) {
|
||||
func TestPeersAlone(t *testing.T) {
|
||||
|
||||
testTx := createTestTxObj(t)
|
||||
testTorrent := createTestTorrent()
|
||||
testTx := createTestTxObj()
|
||||
testTorrentID := createTestTorrentID()
|
||||
testPeers := createTestPeers(testTorrentID, 3)
|
||||
|
||||
setkey := testTx.conf.Prefix + SeederPrefix + strconv.FormatUint(testTorrent.ID, 36)
|
||||
testTx.Do("DEL", setkey)
|
||||
|
||||
testTx.addPeers(testTorrent.Seeders, SeederPrefix)
|
||||
peerMap, err := testTx.getPeers(testTorrent.ID, SeederPrefix)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if len(peerMap) != len(testTorrent.Seeders) {
|
||||
t.Error("Num Peers not equal")
|
||||
panicErrNil(testTx.addPeers(testPeers, "test:"))
|
||||
peerMap, err := testTx.getPeers(testTorrentID, "test:")
|
||||
panicErrNil(err)
|
||||
if len(peerMap) != len(testPeers) {
|
||||
t.Error("Num Peers not equal ", len(peerMap), len(testPeers))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloseClosedTransaction(t *testing.T) {
|
||||
//require panic
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Error("Closing a closed transaction did not panic")
|
||||
}
|
||||
}()
|
||||
|
||||
testTx := createTestTxObj(t)
|
||||
testTx.close()
|
||||
testTx.close()
|
||||
panicErrNil(testTx.removePeers(testTorrentID, testPeers, "test:"))
|
||||
}
|
||||
|
|
367
cache/redis/tx_test.go
vendored
367
cache/redis/tx_test.go
vendored
|
@ -5,7 +5,6 @@
|
|||
package redis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -13,15 +12,9 @@ import (
|
|||
|
||||
"github.com/pushrax/chihaya/cache"
|
||||
"github.com/pushrax/chihaya/config"
|
||||
"github.com/pushrax/chihaya/models"
|
||||
)
|
||||
|
||||
func panicErrNil(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func createTestTx() cache.Tx {
|
||||
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
|
||||
panicErrNil(err)
|
||||
|
@ -38,24 +31,24 @@ func createTestTx() cache.Tx {
|
|||
|
||||
func TestFindUserSuccess(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testUser1 := createTestUser()
|
||||
testUser := createTestUser()
|
||||
|
||||
panicErrNil(tx.AddUser(&testUser1))
|
||||
foundUser, found, err := tx.FindUser(testUser1.Passkey)
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
foundUser, found, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
t.Error("user not found", testUser1)
|
||||
t.Error("user not found", testUser)
|
||||
}
|
||||
if *foundUser != testUser1 {
|
||||
t.Error("found user mismatch", *foundUser, testUser1)
|
||||
if *foundUser != *testUser {
|
||||
t.Error("found user mismatch", *foundUser, testUser)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindUserFail(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testUser2 := createTestUser()
|
||||
testUser := createTestUser()
|
||||
|
||||
foundUser, found, err := tx.FindUser(testUser2.Passkey)
|
||||
foundUser, found, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
t.Error("user found", foundUser)
|
||||
|
@ -64,12 +57,12 @@ func TestFindUserFail(t *testing.T) {
|
|||
|
||||
func TestRemoveUser(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testUser1 := createTestUser()
|
||||
testUser := createTestUser()
|
||||
|
||||
panicErrNil(tx.AddUser(&testUser1))
|
||||
err := tx.RemoveUser(&testUser1)
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
err := tx.RemoveUser(testUser)
|
||||
panicErrNil(err)
|
||||
foundUser, found, err := tx.FindUser(testUser1.Passkey)
|
||||
foundUser, found, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
t.Error("removed user found", foundUser)
|
||||
|
@ -78,25 +71,25 @@ func TestRemoveUser(t *testing.T) {
|
|||
|
||||
func TestFindTorrent(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
testTorrent := createTestTorrent()
|
||||
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
t.Error("torrent not found", testTorrent1)
|
||||
t.Error("torrent not found", testTorrent)
|
||||
}
|
||||
// Incomplete comparison as maps make struct not nativly comparable
|
||||
if foundTorrent.Infohash != testTorrent1.Infohash {
|
||||
t.Error("found torrent mismatch", foundTorrent, testTorrent1)
|
||||
if foundTorrent.Infohash != testTorrent.Infohash {
|
||||
t.Error("found torrent mismatch", foundTorrent, testTorrent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindTorrentFail(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent2 := createTestTorrent()
|
||||
testTorrent := createTestTorrent()
|
||||
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent2.Infohash)
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
t.Error("torrent found", foundTorrent)
|
||||
|
@ -105,11 +98,11 @@ func TestFindTorrentFail(t *testing.T) {
|
|||
|
||||
func TestRemoveTorrent(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
|
||||
panicErrNil(tx.RemoveTorrent(testTorrent1))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.RemoveTorrent(testTorrent))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
t.Error("removed torrent found", foundTorrent)
|
||||
|
@ -118,13 +111,13 @@ func TestRemoveTorrent(t *testing.T) {
|
|||
|
||||
func TestClientWhitelistSuccess(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testPeerID1 := "-lt0D30-"
|
||||
testPeerID := "-lt0D30-"
|
||||
|
||||
panicErrNil(tx.WhitelistClient(testPeerID1))
|
||||
found, err := tx.ClientWhitelisted(testPeerID1)
|
||||
panicErrNil(tx.WhitelistClient(testPeerID))
|
||||
found, err := tx.ClientWhitelisted(testPeerID)
|
||||
panicErrNil(err)
|
||||
if !found {
|
||||
t.Error("peerID not found", testPeerID1)
|
||||
t.Error("peerID not found", testPeerID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,194 +130,282 @@ func TestClientWhitelistFail(t *testing.T) {
|
|||
if found {
|
||||
t.Error("peerID found", testPeerID2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordSnatch(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
testUser := createTestUser()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
|
||||
userSnatches := testUser.Snatches
|
||||
torrentSnatches := testTorrent.Snatches
|
||||
|
||||
panicErrNil(tx.RecordSnatch(testUser, testTorrent))
|
||||
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundUser, _, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
|
||||
if testUser.Snatches != userSnatches+1 {
|
||||
t.Error("snatch not recorded to local user", testUser.Snatches, userSnatches+1)
|
||||
}
|
||||
if testTorrent.Snatches != torrentSnatches+1 {
|
||||
t.Error("snatch not recorded to local torrent")
|
||||
}
|
||||
if foundUser.Snatches != userSnatches+1 {
|
||||
t.Error("snatch not recorded to cached user", foundUser.Snatches, userSnatches+1)
|
||||
}
|
||||
if foundTorrent.Snatches != torrentSnatches+1 {
|
||||
t.Error("snatch not recorded to cached torrent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarkActive(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent := createTestTorrent()
|
||||
testTorrent.Active = false
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
|
||||
panicErrNil(tx.MarkActive(testTorrent))
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
|
||||
if foundTorrent.Active != true {
|
||||
t.Error("cached torrent not activated")
|
||||
}
|
||||
if testTorrent.Active != true {
|
||||
t.Error("cached torrent not activated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientWhitelistRemove(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testPeerID1 := "-lt0D30-"
|
||||
panicErrNil(tx.WhitelistClient(testPeerID1))
|
||||
panicErrNil(tx.UnWhitelistClient(testPeerID1))
|
||||
testPeerID := "-lt0D30-"
|
||||
panicErrNil(tx.WhitelistClient(testPeerID))
|
||||
panicErrNil(tx.UnWhitelistClient(testPeerID))
|
||||
|
||||
found, err := tx.ClientWhitelisted(testPeerID1)
|
||||
found, err := tx.ClientWhitelisted(testPeerID)
|
||||
panicErrNil(err)
|
||||
if found {
|
||||
t.Error("removed peerID found", testPeerID1)
|
||||
t.Error("removed peerID found", testPeerID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddSeeder(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testSeeder1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
|
||||
panicErrNil(tx.AddSeeder(testTorrent1, testSeeder1))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundSeeder, found := foundTorrent.Seeders[testSeeder1.ID]
|
||||
if found && foundSeeder != *testSeeder1 {
|
||||
t.Error("seeder not added to cache", testSeeder1)
|
||||
foundSeeder, found := foundTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if found && foundSeeder != *testSeeder {
|
||||
t.Error("seeder not added to cache", testSeeder)
|
||||
}
|
||||
foundSeeder, found = testTorrent1.Seeders[testSeeder1.ID]
|
||||
if found && foundSeeder != *testSeeder1 {
|
||||
t.Error("seeder not added to local", testSeeder1)
|
||||
foundSeeder, found = testTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if found && foundSeeder != *testSeeder {
|
||||
t.Error("seeder not added to local", testSeeder)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddLeecher(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testLeecher1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
|
||||
tx.AddLeecher(testTorrent1, testLeecher1)
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundLeecher, found := foundTorrent.Leechers[testLeecher1.ID]
|
||||
if found && foundLeecher != *testLeecher1 {
|
||||
t.Error("leecher not added to cache", testLeecher1)
|
||||
foundLeecher, found := foundTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if found && foundLeecher != *testLeecher {
|
||||
t.Error("leecher not added to cache", testLeecher)
|
||||
}
|
||||
foundLeecher, found = testTorrent1.Leechers[testLeecher1.ID]
|
||||
if found && foundLeecher != *testLeecher1 {
|
||||
t.Error("leecher not added to local", testLeecher1)
|
||||
foundLeecher, found = testTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if found && foundLeecher != *testLeecher {
|
||||
t.Error("leecher not added to local", testLeecher)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveSeeder(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testSeeder1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
tx.AddSeeder(testTorrent1, testSeeder1)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
|
||||
panicErrNil(tx.RemoveSeeder(testTorrent1, testSeeder1))
|
||||
foundSeeder, found := testTorrent1.Seeders[testSeeder1.ID]
|
||||
if found || foundSeeder == *testSeeder1 {
|
||||
panicErrNil(tx.RemoveSeeder(testTorrent, testSeeder))
|
||||
foundSeeder, found := testTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if found || foundSeeder == *testSeeder {
|
||||
t.Error("seeder not removed from local", foundSeeder)
|
||||
}
|
||||
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundSeeder, found = foundTorrent.Seeders[testSeeder1.ID]
|
||||
if found || foundSeeder == *testSeeder1 {
|
||||
t.Error("seeder not removed from cache", foundSeeder)
|
||||
foundSeeder, found = foundTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if found || foundSeeder == *testSeeder {
|
||||
t.Error("seeder not removed from cache", foundSeeder, *testSeeder)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveLeecher(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testLeecher1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
tx.AddLeecher(testTorrent1, testLeecher1)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
|
||||
tx.RemoveLeecher(testTorrent1, testLeecher1)
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.RemoveLeecher(testTorrent, testLeecher))
|
||||
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundLeecher, found := foundTorrent.Leechers[testLeecher1.ID]
|
||||
if found || foundLeecher == *testLeecher1 {
|
||||
t.Error("leecher not removed from cache", foundLeecher)
|
||||
foundLeecher, found := foundTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if found || foundLeecher == *testLeecher {
|
||||
t.Error("leecher not removed from cache", foundLeecher, *testLeecher)
|
||||
}
|
||||
foundLeecher, found = testTorrent1.Leechers[testLeecher1.ID]
|
||||
if found || foundLeecher == *testLeecher1 {
|
||||
t.Error("leecher not removed from local", foundLeecher)
|
||||
foundLeecher, found = testTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if found || foundLeecher == *testLeecher {
|
||||
t.Error("leecher not removed from local", foundLeecher, *testLeecher)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSeeder(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testSeeder1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
tx.AddSeeder(testTorrent1, testSeeder1)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
|
||||
testSeeder1.Uploaded += 100
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
testSeeder.Uploaded += uint64(r.Int63())
|
||||
|
||||
tx.SetSeeder(testTorrent1, testSeeder1)
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.SetSeeder(testTorrent, testSeeder))
|
||||
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundSeeder, _ := foundTorrent.Seeders[testSeeder1.ID]
|
||||
if foundSeeder != *testSeeder1 {
|
||||
t.Error("seeder not updated in cache", testSeeder1)
|
||||
foundSeeder, _ := foundTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if foundSeeder != *testSeeder {
|
||||
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
|
||||
}
|
||||
foundSeeder, _ = testTorrent1.Seeders[testSeeder1.ID]
|
||||
if foundSeeder != *testSeeder1 {
|
||||
t.Error("seeder not updated in local", testSeeder1)
|
||||
foundSeeder, _ = testTorrent.Seeders[models.PeerMapKey(testSeeder)]
|
||||
if foundSeeder != *testSeeder {
|
||||
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetLeecher(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testLeecher1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
tx.AddLeecher(testTorrent1, testLeecher1)
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
|
||||
testLeecher1.Uploaded += 100
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
testLeecher.Uploaded += uint64(r.Int63())
|
||||
|
||||
tx.SetLeecher(testTorrent1, testLeecher1)
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.SetLeecher(testTorrent, testLeecher))
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundLeecher, _ := foundTorrent.Leechers[testLeecher1.ID]
|
||||
if foundLeecher != *testLeecher1 {
|
||||
t.Error("leecher not updated in cache", testLeecher1)
|
||||
foundLeecher, _ := foundTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if foundLeecher != *testLeecher {
|
||||
t.Error("leecher not updated in cache", testLeecher)
|
||||
}
|
||||
foundLeecher, _ = testTorrent1.Leechers[testLeecher1.ID]
|
||||
if foundLeecher != *testLeecher1 {
|
||||
t.Error("leecher not updated in local", testLeecher1)
|
||||
foundLeecher, _ = testTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if foundLeecher != *testLeecher {
|
||||
t.Error("leecher not updated in local", testLeecher)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncrementSlots(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testUser := createTestUser()
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
numSlots := testUser.Slots
|
||||
|
||||
panicErrNil(tx.IncrementSlots(testUser))
|
||||
foundUser, _, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
|
||||
if foundUser.Slots != numSlots+1 {
|
||||
t.Error("cached slots not incremented")
|
||||
}
|
||||
if testUser.Slots != numSlots+1 {
|
||||
t.Error("local slots not incremented")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecrementSlots(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testUser := createTestUser()
|
||||
panicErrNil(tx.AddUser(testUser))
|
||||
numSlots := testUser.Slots
|
||||
|
||||
panicErrNil(tx.DecrementSlots(testUser))
|
||||
foundUser, _, err := tx.FindUser(testUser.Passkey)
|
||||
panicErrNil(err)
|
||||
|
||||
if foundUser.Slots != numSlots-1 {
|
||||
t.Error("cached slots not incremented")
|
||||
}
|
||||
if testUser.Slots != numSlots-1 {
|
||||
t.Error("local slots not incremented")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeecherFinished(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
testLeecher1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
tx.AddLeecher(testTorrent1, testLeecher1)
|
||||
testLeecher1.Left = 0
|
||||
testTorrent := createTestTorrent()
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
|
||||
testLeecher.Left = 0
|
||||
|
||||
tx.LeecherFinished(testTorrent1, testLeecher1)
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.LeecherFinished(testTorrent, testLeecher))
|
||||
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
foundSeeder, _ := foundTorrent.Seeders[testLeecher1.ID]
|
||||
if foundSeeder != *testLeecher1 {
|
||||
t.Error("seeder not added to cache", testLeecher1, foundSeeder)
|
||||
foundSeeder, _ := foundTorrent.Seeders[models.PeerMapKey(testLeecher)]
|
||||
if foundSeeder != *testLeecher {
|
||||
t.Error("seeder not added to cache", foundSeeder, *testLeecher)
|
||||
}
|
||||
foundSeeder, _ = foundTorrent.Leechers[testLeecher1.ID]
|
||||
if foundSeeder == *testLeecher1 {
|
||||
t.Error("leecher not removed from cache", testLeecher1)
|
||||
foundSeeder, _ = foundTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if foundSeeder == *testLeecher {
|
||||
t.Error("leecher not removed from cache", testLeecher)
|
||||
}
|
||||
foundSeeder, _ = testTorrent1.Seeders[testLeecher1.ID]
|
||||
if foundSeeder != *testLeecher1 {
|
||||
t.Error("seeder not added to local", testLeecher1)
|
||||
foundSeeder, _ = testTorrent.Seeders[models.PeerMapKey(testLeecher)]
|
||||
if foundSeeder != *testLeecher {
|
||||
t.Error("seeder not added to local", testLeecher)
|
||||
}
|
||||
foundSeeder, _ = testTorrent1.Leechers[testLeecher1.ID]
|
||||
if foundSeeder == *testLeecher1 {
|
||||
t.Error("leecher not removed from local", testLeecher1)
|
||||
foundSeeder, _ = testTorrent.Leechers[models.PeerMapKey(testLeecher)]
|
||||
if foundSeeder == *testLeecher {
|
||||
t.Error("leecher not removed from local", testLeecher)
|
||||
}
|
||||
}
|
||||
|
||||
// Add, update, verify remove
|
||||
func TestUpdatePeer(t *testing.T) {
|
||||
tx := createTestTx()
|
||||
testTorrent1 := createTestTorrent()
|
||||
testSeeder1 := createTestPeer(createTestUserID(), testTorrent1.ID)
|
||||
panicErrNil(tx.AddTorrent(testTorrent1))
|
||||
panicErrNil(tx.AddSeeder(testTorrent1, testSeeder1))
|
||||
testTorrent := createTestTorrent()
|
||||
testSeeder := createTestPeer(createTestUserID(), testTorrent.ID)
|
||||
panicErrNil(tx.AddTorrent(testTorrent))
|
||||
panicErrNil(tx.AddSeeder(testTorrent, testSeeder))
|
||||
// Update a seeder, set it, then check to make sure it updated
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
testSeeder1.Uploaded += uint64(r.Int63())
|
||||
testSeeder.Uploaded += uint64(r.Int63())
|
||||
|
||||
panicErrNil(tx.SetSeeder(testTorrent1, testSeeder1))
|
||||
panicErrNil(tx.SetSeeder(testTorrent, testSeeder))
|
||||
|
||||
panicErrNil(tx.RemoveSeeder(testTorrent1, testSeeder1))
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent1.Infohash)
|
||||
panicErrNil(tx.RemoveSeeder(testTorrent, testSeeder))
|
||||
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
|
||||
panicErrNil(err)
|
||||
if seeder1, exists := foundTorrent.Seeders[testSeeder1.ID]; exists {
|
||||
t.Error("seeder not removed from cache", seeder1)
|
||||
if seeder, exists := foundTorrent.Seeders[models.PeerMapKey(testSeeder)]; exists {
|
||||
t.Error("seeder not removed from cache", seeder)
|
||||
}
|
||||
if seeder1, exists := testTorrent1.Seeders[testSeeder1.ID]; exists {
|
||||
t.Error("seeder not removed from local", seeder1)
|
||||
if seeder, exists := testTorrent.Seeders[models.PeerMapKey(testSeeder)]; exists {
|
||||
t.Error("seeder not removed from local", seeder)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
package models
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
ID string `json:"id"`
|
||||
UserID uint64 `json:"user_id"`
|
||||
|
@ -18,6 +22,10 @@ type Peer struct {
|
|||
LastAnnounce int64 `json:"last_announce"`
|
||||
}
|
||||
|
||||
func PeerMapKey(peer *Peer) string {
|
||||
return peer.ID + ":" + strconv.FormatUint(peer.UserID, 36)
|
||||
}
|
||||
|
||||
type Torrent struct {
|
||||
ID uint64 `json:"id"`
|
||||
Infohash string `json:"infohash"`
|
||||
|
|
|
@ -82,8 +82,8 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Look for the user in in the pool of seeders and leechers
|
||||
_, seeder := torrent.Seeders[peerID]
|
||||
_, leecher := torrent.Leechers[peerID]
|
||||
_, seeder := torrent.Seeders[models.PeerMapKey(peer)]
|
||||
_, leecher := torrent.Leechers[models.PeerMapKey(peer)]
|
||||
|
||||
switch {
|
||||
// Guarantee that no user is in both pools
|
||||
|
|
Loading…
Add table
Reference in a new issue