Added parallel tests

This commit is contained in:
cpb8010 2013-09-19 00:27:10 -04:00
parent 1ea24f80dc
commit 19900991a7
3 changed files with 207 additions and 27 deletions

View file

@ -297,14 +297,17 @@ func (tx *Tx) getPeers(torrentID uint64, peerTypePrefix string) (peers map[strin
setKey := tx.conf.Prefix + peerTypePrefix + strconv.FormatUint(torrentID, 36) setKey := tx.conf.Prefix + peerTypePrefix + strconv.FormatUint(torrentID, 36)
peerStrings, err := redis.Strings(tx.Do("SMEMBERS", setKey)) peerStrings, err := redis.Strings(tx.Do("SMEMBERS", setKey))
if err != nil { if err != nil {
return peers, err return nil, err
} }
// Keys map to peer objects stored in hashes // Keys map to peer objects stored in hashes
for _, peerHashKey := range peerStrings { for _, peerHashKey := range peerStrings {
hashKey := tx.conf.Prefix + peerHashKey hashKey := tx.conf.Prefix + peerHashKey
peerVals, err := redis.Strings(tx.Do("HVALS", hashKey)) peerVals, err := redis.Strings(tx.Do("HVALS", hashKey))
if err != nil { if err != nil {
return peers, err return nil, err
}
if len(peerVals) == 0 {
continue
} }
peer, err := createPeer(peerVals) peer, err := createPeer(peerVals)
if err != nil { if err != nil {

View file

@ -19,24 +19,43 @@ import (
) )
var ( var (
testTorrentIDCounter uint64 testTorrentIDChannel chan uint64
testUserIDCounter uint64 testUserIDChannel chan uint64
testPeerIDCounter int testPeerIDChannel chan int
) )
func init() {
testTorrentIDChannel = make(chan uint64, 100)
testUserIDChannel = make(chan uint64, 100)
testPeerIDChannel = make(chan int, 100)
// Sync access to ID counter with buffered global channels
go func() {
for i := 0; ; i++ {
testTorrentIDChannel <- uint64(i)
}
}()
go func() {
for i := 0; ; i++ {
testUserIDChannel <- uint64(i)
}
}()
go func() {
for i := 0; ; i++ {
testPeerIDChannel <- i
}
}()
}
func createTestTorrentID() uint64 { func createTestTorrentID() uint64 {
testTorrentIDCounter++ return <-testTorrentIDChannel
return testTorrentIDCounter
} }
func createTestUserID() uint64 { func createTestUserID() uint64 {
testUserIDCounter++ return <-testUserIDChannel
return testUserIDCounter
} }
func createTestPeerID() string { func createTestPeerID() string {
testPeerIDCounter++ return "-testPeerID-" + strconv.Itoa(<-testPeerIDChannel)
return "-testPeerID-" + strconv.Itoa(testPeerIDCounter)
} }
func createTestInfohash() string { func createTestInfohash() string {
@ -57,14 +76,6 @@ func createTestPasskey() string {
return string(uuid) return string(uuid)
} }
// Common interface for benchmarks and test error reporting
type TestReporter interface {
Error(args ...interface{})
Errorf(format string, args ...interface{})
Log(args ...interface{})
Logf(format string, args ...interface{})
}
func panicErrNil(err error) { func panicErrNil(err error) {
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
@ -72,7 +83,7 @@ func panicErrNil(err error) {
} }
} }
func createTestTxObj() *Tx { func createTestRedisTx() *Tx {
testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH")) testConfig, err := config.Open(os.Getenv("TESTCONFIGPATH"))
conf := &testConfig.Cache conf := &testConfig.Cache
panicErrNil(err) panicErrNil(err)
@ -115,7 +126,7 @@ func createTestPeers(torrentID uint64, num int) map[string]models.Peer {
testPeers := make(map[string]models.Peer) testPeers := make(map[string]models.Peer)
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
tempPeer := createTestPeer(createTestUserID(), torrentID) tempPeer := createTestPeer(createTestUserID(), torrentID)
testPeers[tempPeer.ID] = *tempPeer testPeers[models.PeerMapKey(tempPeer)] = *tempPeer
} }
return testPeers return testPeers
} }
@ -133,9 +144,43 @@ func createTestTorrent() *models.Torrent {
return &testTorrent return &testTorrent
} }
func TestPeersAlone(t *testing.T) { func comparePeers(lhPeers map[string]models.Peer, rhPeers map[string]models.Peer) bool {
if len(lhPeers) != len(rhPeers) {
return false
}
for rhKey, rhValue := range rhPeers {
lhValue, lhExists := lhPeers[rhKey]
if !lhExists || lhValue != rhValue {
return false
}
}
for lhKey, lhValue := range lhPeers {
rhValue, rhExists := rhPeers[lhKey]
if !rhExists || rhValue != lhValue {
return false
}
}
return true
}
testTx := createTestTxObj() func torrentsEqual(lhTorrent *models.Torrent, rhTorrent *models.Torrent) bool {
fieldsEqual := lhTorrent.Infohash == rhTorrent.Infohash &&
lhTorrent.ID == rhTorrent.ID &&
lhTorrent.Active == rhTorrent.Active &&
lhTorrent.Snatches == rhTorrent.Snatches &&
lhTorrent.UpMultiplier == rhTorrent.UpMultiplier &&
lhTorrent.DownMultiplier == rhTorrent.DownMultiplier &&
lhTorrent.LastAction == rhTorrent.LastAction
if !fieldsEqual {
return false
}
return comparePeers(lhTorrent.Seeders, rhTorrent.Seeders) && comparePeers(lhTorrent.Leechers, rhTorrent.Leechers)
}
func TestValidPeers(t *testing.T) {
testTx := createTestRedisTx()
testTorrentID := createTestTorrentID() testTorrentID := createTestTorrentID()
testPeers := createTestPeers(testTorrentID, 3) testPeers := createTestPeers(testTorrentID, 3)
@ -147,3 +192,25 @@ func TestPeersAlone(t *testing.T) {
} }
panicErrNil(testTx.removePeers(testTorrentID, testPeers, "test:")) panicErrNil(testTx.removePeers(testTorrentID, testPeers, "test:"))
} }
func TestInvalidPeers(t *testing.T) {
testTx := createTestRedisTx()
testTorrentID := createTestTorrentID()
testPeers := createTestPeers(testTorrentID, 3)
tempPeer := createTestPeer(createTestUserID(), testTorrentID)
testPeers[models.PeerMapKey(tempPeer)] = *tempPeer
panicErrNil(testTx.addPeers(testPeers, "test:"))
// Imitate a peer being removed during get
hashKey := testTx.conf.Prefix + getPeerHashKey(tempPeer)
_, err := testTx.Do("DEL", hashKey)
panicErrNil(err)
peerMap, err := testTx.getPeers(testTorrentID, "test:")
panicErrNil(err)
// Expect 1 less peer due to delete
if len(peerMap) != len(testPeers)-1 {
t.Error("Num Peers not equal ", len(peerMap), len(testPeers))
}
panicErrNil(testTx.removePeers(testTorrentID, testPeers, "test:"))
}

118
cache/redis/tx_test.go vendored
View file

@ -69,18 +69,17 @@ func TestRemoveUser(t *testing.T) {
} }
} }
func TestFindTorrent(t *testing.T) { func TestFindTorrentSuccess(t *testing.T) {
tx := createTestTx() tx := createTestTx()
testTorrent := createTestTorrent() testTorrent := createTestTorrent()
panicErrNil(tx.AddTorrent(testTorrent)) panicErrNil(tx.AddTorrent(testTorrent))
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash) foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
panicErrNil(err) panicErrNil(err)
if !found { if !found {
t.Error("torrent not found", testTorrent) t.Error("torrent not found", testTorrent)
} }
// Incomplete comparison as maps make struct not nativly comparable if !torrentsEqual(foundTorrent, testTorrent) {
if foundTorrent.Infohash != testTorrent.Infohash {
t.Error("found torrent mismatch", foundTorrent, testTorrent) t.Error("found torrent mismatch", foundTorrent, testTorrent)
} }
} }
@ -409,3 +408,114 @@ func TestUpdatePeer(t *testing.T) {
t.Error("seeder not removed from local", seeder) t.Error("seeder not removed from local", seeder)
} }
} }
func TestParallelFindUser(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip()
}
tx := createTestTx()
testUserSuccess := createTestUser()
testUserFail := createTestUser()
panicErrNil(tx.AddUser(testUserSuccess))
for i := 0; i < 10; i++ {
foundUser, found, err := tx.FindUser(testUserFail.Passkey)
panicErrNil(err)
if found {
t.Error("user found", foundUser)
}
foundUser, found, err = tx.FindUser(testUserSuccess.Passkey)
panicErrNil(err)
if !found {
t.Error("user not found", testUserSuccess)
}
if *foundUser != *testUserSuccess {
t.Error("found user mismatch", *foundUser, testUserSuccess)
}
}
}
func TestParallelFindTorrent(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip()
}
tx := createTestTx()
testTorrentSuccess := createTestTorrent()
testTorrentFail := createTestTorrent()
panicErrNil(tx.AddTorrent(testTorrentSuccess))
for i := 0; i < 10; i++ {
foundTorrent, found, err := tx.FindTorrent(testTorrentSuccess.Infohash)
panicErrNil(err)
if !found {
t.Error("torrent not found", testTorrentSuccess)
}
if !torrentsEqual(foundTorrent, testTorrentSuccess) {
t.Error("found torrent mismatch", foundTorrent, testTorrentSuccess)
}
foundTorrent, found, err = tx.FindTorrent(testTorrentFail.Infohash)
panicErrNil(err)
if found {
t.Error("torrent found", foundTorrent)
}
}
}
func TestParallelSetSeeder(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip()
}
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()))
for i := 0; i < 10; i++ {
testSeeder.Uploaded += uint64(r.Int63())
panicErrNil(tx.SetSeeder(testTorrent, testSeeder))
foundTorrent, _, err := tx.FindTorrent(testTorrent.Infohash)
panicErrNil(err)
foundSeeder, _ := foundTorrent.Seeders[models.PeerMapKey(testSeeder)]
if foundSeeder != *testSeeder {
t.Error("seeder not updated in cache", foundSeeder, *testSeeder)
}
foundSeeder, _ = testTorrent.Seeders[models.PeerMapKey(testSeeder)]
if foundSeeder != *testSeeder {
t.Error("seeder not updated in local", foundSeeder, *testSeeder)
}
}
}
func TestParallelAddLeecher(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip()
}
tx := createTestTx()
testTorrent := createTestTorrent()
panicErrNil(tx.AddTorrent(testTorrent))
for i := 0; i < 10; i++ {
testLeecher := createTestPeer(createTestUserID(), testTorrent.ID)
panicErrNil(tx.AddLeecher(testTorrent, testLeecher))
foundTorrent, found, err := tx.FindTorrent(testTorrent.Infohash)
panicErrNil(err)
foundLeecher, found := foundTorrent.Leechers[models.PeerMapKey(testLeecher)]
if found && foundLeecher != *testLeecher {
t.Error("leecher not added to cache", testLeecher)
}
foundLeecher, found = testTorrent.Leechers[models.PeerMapKey(testLeecher)]
if found && foundLeecher != *testLeecher {
t.Error("leecher not added to local", testLeecher)
}
}
}