ba5f71810e
* added tally to capt run.go, ParseURL -> SplitDBURL
466 lines
14 KiB
Go
466 lines
14 KiB
Go
// Copyright (C) 2018 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package statdb_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"go.uber.org/zap"
|
|
"storj.io/storj/internal/teststorj"
|
|
"storj.io/storj/pkg/statdb"
|
|
dbx "storj.io/storj/pkg/statdb/dbx"
|
|
pb "storj.io/storj/pkg/statdb/proto"
|
|
"storj.io/storj/pkg/storj"
|
|
)
|
|
|
|
var (
|
|
ctx = context.Background()
|
|
)
|
|
|
|
func TestCreateDoesNotExist(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
node := &pb.Node{Id: nodeID}
|
|
createReq := &pb.CreateRequest{
|
|
Node: node,
|
|
}
|
|
resp, err := statdb.Create(ctx, createReq)
|
|
assert.NoError(t, err)
|
|
stats := resp.Stats
|
|
assert.EqualValues(t, 0, stats.AuditSuccessRatio)
|
|
assert.EqualValues(t, 0, stats.UptimeRatio)
|
|
|
|
nodeInfo, err := db.Get_Node_By_Id(ctx, dbx.Node_Id(nodeID.Bytes()))
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, nodeID.Bytes(), nodeInfo.Id)
|
|
assert.EqualValues(t, 0, nodeInfo.AuditSuccessRatio)
|
|
assert.EqualValues(t, 0, nodeInfo.UptimeRatio)
|
|
}
|
|
|
|
func TestCreateExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID, auditSuccessCount, totalAuditCount, auditRatio,
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio)
|
|
assert.NoError(t, err)
|
|
|
|
node := &pb.Node{Id: nodeID}
|
|
createReq := &pb.CreateRequest{
|
|
Node: node,
|
|
}
|
|
_, err = statdb.Create(ctx, createReq)
|
|
assert.Error(t, err)
|
|
}
|
|
func TestCreateWithStats(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
node := &pb.Node{Id: nodeID}
|
|
stats := &pb.NodeStats{
|
|
AuditCount: totalAuditCount,
|
|
AuditSuccessCount: auditSuccessCount,
|
|
UptimeCount: totalUptimeCount,
|
|
UptimeSuccessCount: uptimeSuccessCount,
|
|
}
|
|
createReq := &pb.CreateRequest{
|
|
Node: node,
|
|
Stats: stats,
|
|
}
|
|
resp, err := statdb.Create(ctx, createReq)
|
|
assert.NoError(t, err)
|
|
s := resp.Stats
|
|
assert.EqualValues(t, auditRatio, s.AuditSuccessRatio)
|
|
assert.EqualValues(t, uptimeRatio, s.UptimeRatio)
|
|
|
|
nodeInfo, err := db.Get_Node_By_Id(ctx, dbx.Node_Id(nodeID.Bytes()))
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, nodeID.Bytes(), nodeInfo.Id)
|
|
assert.EqualValues(t, auditRatio, nodeInfo.AuditSuccessRatio)
|
|
assert.EqualValues(t, uptimeRatio, nodeInfo.UptimeRatio)
|
|
}
|
|
|
|
func TestGetExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
|
|
err = createNode(ctx, db, nodeID, auditSuccessCount, totalAuditCount, auditRatio,
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio)
|
|
assert.NoError(t, err)
|
|
|
|
getReq := &pb.GetRequest{
|
|
NodeId: nodeID,
|
|
}
|
|
resp, err := statdb.Get(ctx, getReq)
|
|
assert.NoError(t, err)
|
|
|
|
stats := resp.Stats
|
|
assert.EqualValues(t, auditRatio, stats.AuditSuccessRatio)
|
|
assert.EqualValues(t, uptimeRatio, stats.UptimeRatio)
|
|
}
|
|
|
|
func TestGetDoesNotExist(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, _, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
getReq := &pb.GetRequest{
|
|
NodeId: nodeID,
|
|
}
|
|
_, err = statdb.Get(ctx, getReq)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestFindInvalidNodes(t *testing.T) {
|
|
NodeIDs := teststorj.NodeIDsFromStrings("id1", "id2", "id3", "id4", "id5", "id6", "id7")
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
for _, tt := range []struct {
|
|
nodeID storj.NodeID
|
|
auditSuccessCount int64
|
|
totalAuditCount int64
|
|
auditRatio float64
|
|
uptimeSuccessCount int64
|
|
totalUptimeCount int64
|
|
uptimeRatio float64
|
|
}{
|
|
{NodeIDs[0], 20, 20, 1, 20, 20, 1}, // good audit success
|
|
{NodeIDs[1], 5, 20, 0.25, 20, 20, 1}, // bad audit success, good uptime
|
|
{NodeIDs[2], 20, 20, 1, 5, 20, 0.25}, // good audit success, bad uptime
|
|
{NodeIDs[3], 0, 0, 0, 20, 20, 1}, // "bad" audit success, no audits
|
|
{NodeIDs[4], 20, 20, 1, 0, 0, 0}, // "bad" uptime success, no checks
|
|
{NodeIDs[5], 0, 1, 0, 5, 5, 1}, // bad audit success exactly one audit
|
|
{NodeIDs[6], 0, 20, 0, 20, 20, 1}, // bad ratios, excluded from query
|
|
} {
|
|
err = createNode(ctx, db, tt.nodeID, tt.auditSuccessCount, tt.totalAuditCount, tt.auditRatio,
|
|
tt.uptimeSuccessCount, tt.totalUptimeCount, tt.uptimeRatio)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
findInvalidNodesReq := &pb.FindInvalidNodesRequest{
|
|
NodeIds: storj.NodeIDList{
|
|
NodeIDs[0], NodeIDs[1],
|
|
NodeIDs[2], NodeIDs[3],
|
|
NodeIDs[4], NodeIDs[5],
|
|
},
|
|
MaxStats: &pb.NodeStats{
|
|
AuditSuccessRatio: 0.5,
|
|
UptimeRatio: 0.5,
|
|
},
|
|
}
|
|
|
|
resp, err := statdb.FindInvalidNodes(ctx, findInvalidNodesReq)
|
|
assert.NoError(t, err)
|
|
|
|
invalid := resp.InvalidIds
|
|
|
|
assert.Contains(t, invalid, NodeIDs[1])
|
|
assert.Contains(t, invalid, NodeIDs[2])
|
|
assert.Contains(t, invalid, NodeIDs[5])
|
|
assert.Len(t, invalid, 3)
|
|
}
|
|
|
|
func TestUpdateExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID, auditSuccessCount, totalAuditCount, auditRatio,
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio)
|
|
assert.NoError(t, err)
|
|
|
|
node := &pb.Node{
|
|
Id: nodeID,
|
|
UpdateAuditSuccess: true,
|
|
AuditSuccess: true,
|
|
UpdateUptime: true,
|
|
IsUp: false,
|
|
}
|
|
updateReq := &pb.UpdateRequest{
|
|
Node: node,
|
|
}
|
|
resp, err := statdb.Update(ctx, updateReq)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, newAuditRatio := getRatio(int(auditSuccessCount+1), int(totalAuditCount+1))
|
|
_, _, newUptimeRatio := getRatio(int(uptimeSuccessCount), int(totalUptimeCount+1))
|
|
stats := resp.Stats
|
|
assert.EqualValues(t, newAuditRatio, stats.AuditSuccessRatio)
|
|
assert.EqualValues(t, newUptimeRatio, stats.UptimeRatio)
|
|
}
|
|
|
|
func TestUpdateUptimeExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID, auditSuccessCount, totalAuditCount, auditRatio,
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio)
|
|
assert.NoError(t, err)
|
|
|
|
node := &pb.Node{
|
|
Id: nodeID,
|
|
IsUp: false,
|
|
}
|
|
updateReq := &pb.UpdateUptimeRequest{
|
|
Node: node,
|
|
}
|
|
resp, err := statdb.UpdateUptime(ctx, updateReq)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, newUptimeRatio := getRatio(int(uptimeSuccessCount), int(totalUptimeCount+1))
|
|
stats := resp.Stats
|
|
assert.EqualValues(t, auditRatio, stats.AuditSuccessRatio)
|
|
assert.EqualValues(t, totalAuditCount, stats.AuditCount)
|
|
assert.EqualValues(t, newUptimeRatio, stats.UptimeRatio)
|
|
}
|
|
|
|
func TestUpdateAuditSuccessExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID := teststorj.NodeIDFromString("testnodeid")
|
|
|
|
auditSuccessCount, totalAuditCount, auditRatio := getRatio(4, 10)
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID, auditSuccessCount, totalAuditCount, auditRatio,
|
|
uptimeSuccessCount, totalUptimeCount, uptimeRatio)
|
|
assert.NoError(t, err)
|
|
|
|
node := &pb.Node{
|
|
Id: nodeID,
|
|
AuditSuccess: false,
|
|
}
|
|
updateReq := &pb.UpdateAuditSuccessRequest{
|
|
Node: node,
|
|
}
|
|
resp, err := statdb.UpdateAuditSuccess(ctx, updateReq)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, newAuditRatio := getRatio(int(auditSuccessCount), int(totalAuditCount+1))
|
|
stats := resp.Stats
|
|
assert.EqualValues(t, newAuditRatio, stats.AuditSuccessRatio)
|
|
assert.EqualValues(t, totalAuditCount+1, stats.AuditCount)
|
|
assert.EqualValues(t, uptimeRatio, stats.UptimeRatio)
|
|
}
|
|
|
|
func TestUpdateBatchExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID1 := teststorj.NodeIDFromString("testnodeid1")
|
|
nodeID2 := teststorj.NodeIDFromString("testnodeid2")
|
|
|
|
auditSuccessCount1, totalAuditCount1, auditRatio1 := getRatio(4, 10)
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1 := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID1, auditSuccessCount1, totalAuditCount1, auditRatio1,
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1)
|
|
assert.NoError(t, err)
|
|
auditSuccessCount2, totalAuditCount2, auditRatio2 := getRatio(7, 10)
|
|
uptimeSuccessCount2, totalUptimeCount2, uptimeRatio2 := getRatio(8, 20)
|
|
err = createNode(ctx, db, nodeID2, auditSuccessCount2, totalAuditCount2, auditRatio2,
|
|
uptimeSuccessCount2, totalUptimeCount2, uptimeRatio2)
|
|
assert.NoError(t, err)
|
|
|
|
node1 := &pb.Node{
|
|
Id: nodeID1,
|
|
UpdateAuditSuccess: true,
|
|
AuditSuccess: true,
|
|
UpdateUptime: true,
|
|
IsUp: false,
|
|
}
|
|
node2 := &pb.Node{
|
|
Id: nodeID2,
|
|
UpdateAuditSuccess: true,
|
|
AuditSuccess: true,
|
|
UpdateUptime: false,
|
|
}
|
|
updateBatchReq := &pb.UpdateBatchRequest{
|
|
NodeList: []*pb.Node{node1, node2},
|
|
}
|
|
resp, err := statdb.UpdateBatch(ctx, updateBatchReq)
|
|
assert.NoError(t, err)
|
|
|
|
_, _, newAuditRatio1 := getRatio(int(auditSuccessCount1+1), int(totalAuditCount1+1))
|
|
_, _, newUptimeRatio1 := getRatio(int(uptimeSuccessCount1), int(totalUptimeCount1+1))
|
|
_, _, newAuditRatio2 := getRatio(int(auditSuccessCount2+1), int(totalAuditCount2+1))
|
|
stats1 := resp.StatsList[0]
|
|
stats2 := resp.StatsList[1]
|
|
assert.EqualValues(t, newAuditRatio1, stats1.AuditSuccessRatio)
|
|
assert.EqualValues(t, newUptimeRatio1, stats1.UptimeRatio)
|
|
assert.EqualValues(t, newAuditRatio2, stats2.AuditSuccessRatio)
|
|
assert.EqualValues(t, uptimeRatio2, stats2.UptimeRatio)
|
|
}
|
|
|
|
func TestUpdateBatchDoesNotExist(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID1 := teststorj.NodeIDFromString("testnodeid1")
|
|
nodeID2 := teststorj.NodeIDFromString("testnodeid2")
|
|
|
|
auditSuccessCount1, totalAuditCount1, auditRatio1 := getRatio(4, 10)
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1 := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID1, auditSuccessCount1, totalAuditCount1, auditRatio1,
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1)
|
|
assert.NoError(t, err)
|
|
|
|
node1 := &pb.Node{
|
|
Id: nodeID1,
|
|
UpdateAuditSuccess: true,
|
|
AuditSuccess: true,
|
|
UpdateUptime: true,
|
|
IsUp: false,
|
|
}
|
|
node2 := &pb.Node{
|
|
Id: nodeID2,
|
|
UpdateAuditSuccess: true,
|
|
AuditSuccess: true,
|
|
UpdateUptime: false,
|
|
}
|
|
updateBatchReq := &pb.UpdateBatchRequest{
|
|
NodeList: []*pb.Node{node1, node2},
|
|
}
|
|
_, err = statdb.UpdateBatch(ctx, updateBatchReq)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestUpdateBatchEmpty(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID1 := teststorj.NodeIDFromString("testnodeid1")
|
|
|
|
auditSuccessCount1, totalAuditCount1, auditRatio1 := getRatio(4, 10)
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1 := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID1, auditSuccessCount1, totalAuditCount1, auditRatio1,
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1)
|
|
assert.NoError(t, err)
|
|
|
|
updateBatchReq := &pb.UpdateBatchRequest{
|
|
NodeList: []*pb.Node{},
|
|
}
|
|
resp, err := statdb.UpdateBatch(ctx, updateBatchReq)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, len(resp.StatsList), 0)
|
|
}
|
|
|
|
func TestCreateEntryIfNotExists(t *testing.T) {
|
|
dbPath := getDBPath()
|
|
statdb, db, err := getServerAndDB(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
nodeID1 := teststorj.NodeIDFromString("testnodeid1")
|
|
nodeID2 := teststorj.NodeIDFromString("testnodeid2")
|
|
|
|
auditSuccessCount1, totalAuditCount1, auditRatio1 := getRatio(4, 10)
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1 := getRatio(8, 25)
|
|
err = createNode(ctx, db, nodeID1, auditSuccessCount1, totalAuditCount1, auditRatio1,
|
|
uptimeSuccessCount1, totalUptimeCount1, uptimeRatio1)
|
|
assert.NoError(t, err)
|
|
|
|
node1 := &pb.Node{Id: nodeID1}
|
|
createIfNotExistsReq1 := &pb.CreateEntryIfNotExistsRequest{
|
|
Node: node1,
|
|
}
|
|
_, err = statdb.CreateEntryIfNotExists(ctx, createIfNotExistsReq1)
|
|
assert.NoError(t, err)
|
|
|
|
nodeInfo1, err := db.Get_Node_By_Id(ctx, dbx.Node_Id(nodeID1.Bytes()))
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, nodeID1.Bytes(), nodeInfo1.Id)
|
|
assert.EqualValues(t, auditRatio1, nodeInfo1.AuditSuccessRatio)
|
|
assert.EqualValues(t, uptimeRatio1, nodeInfo1.UptimeRatio)
|
|
|
|
node2 := &pb.Node{Id: nodeID2}
|
|
createIfNotExistsReq2 := &pb.CreateEntryIfNotExistsRequest{
|
|
Node: node2,
|
|
}
|
|
_, err = statdb.CreateEntryIfNotExists(ctx, createIfNotExistsReq2)
|
|
assert.NoError(t, err)
|
|
|
|
nodeInfo2, err := db.Get_Node_By_Id(ctx, dbx.Node_Id(nodeID2.Bytes()))
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, nodeID2.Bytes(), nodeInfo2.Id)
|
|
assert.EqualValues(t, 0, nodeInfo2.AuditSuccessRatio)
|
|
assert.EqualValues(t, 0, nodeInfo2.UptimeRatio)
|
|
}
|
|
|
|
func getDBPath() string {
|
|
return fmt.Sprintf("file:memdb%d?mode=memory&cache=shared", rand.Int63())
|
|
}
|
|
|
|
func getServerAndDB(path string) (sdb *statdb.StatDB, db *dbx.DB, err error) {
|
|
sdb, err = statdb.NewStatDB("sqlite3", path, zap.NewNop())
|
|
if err != nil {
|
|
return &statdb.StatDB{}, &dbx.DB{}, err
|
|
}
|
|
db, err = dbx.Open("sqlite3", path)
|
|
if err != nil {
|
|
return &statdb.StatDB{}, &dbx.DB{}, err
|
|
}
|
|
return sdb, db, err
|
|
}
|
|
|
|
func createNode(ctx context.Context, db *dbx.DB, nodeID storj.NodeID,
|
|
auditSuccessCount, totalAuditCount int64, auditRatio float64,
|
|
uptimeSuccessCount, totalUptimeCount int64, uptimeRatio float64) error {
|
|
_, err := db.Create_Node(
|
|
ctx,
|
|
dbx.Node_Id(nodeID.Bytes()),
|
|
dbx.Node_AuditSuccessCount(auditSuccessCount),
|
|
dbx.Node_TotalAuditCount(totalAuditCount),
|
|
dbx.Node_AuditSuccessRatio(auditRatio),
|
|
dbx.Node_UptimeSuccessCount(uptimeSuccessCount),
|
|
dbx.Node_TotalUptimeCount(totalUptimeCount),
|
|
dbx.Node_UptimeRatio(uptimeRatio),
|
|
)
|
|
return err
|
|
}
|
|
|
|
func getRatio(s, t int) (success, total int64, ratio float64) {
|
|
ratio = float64(s) / float64(t)
|
|
return int64(s), int64(t), ratio
|
|
}
|