mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-13 14:39:28 +00:00
Added more tests
This commit is contained in:
@@ -467,3 +467,87 @@ func TestProcessDoc(t *testing.T) {
|
|||||||
t.Errorf("Error in ProcessDoc.\nGot:%#v\nWant: %#v\n", stats, want)
|
t.Errorf("Error in ProcessDoc.\nGot:%#v\nWant: %#v\n", stats, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimesLen(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
a times
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Times.Len",
|
||||||
|
a: []time.Time{time.Now()},
|
||||||
|
want: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := tt.a.Len(); got != tt.want {
|
||||||
|
t.Errorf("times.Len() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimesSwap(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
i int
|
||||||
|
j int
|
||||||
|
}
|
||||||
|
t1 := time.Now()
|
||||||
|
t2 := t1.Add(1 * time.Minute)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
a times
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Times.Swap",
|
||||||
|
a: times{t1, t2},
|
||||||
|
args: args{i: 0, j: 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.a.Swap(tt.args.i, tt.args.j)
|
||||||
|
if tt.a[0] != t2 || tt.a[1] != t1 {
|
||||||
|
t.Errorf("%s has (%v, %v) want (%v, %v)", tt.name, tt.a[0], tt.a[1], t2, t1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimesLess(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
i int
|
||||||
|
j int
|
||||||
|
}
|
||||||
|
t1 := time.Now()
|
||||||
|
t2 := t1.Add(1 * time.Minute)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
a times
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Times.Swap",
|
||||||
|
a: times{t1, t2},
|
||||||
|
args: args{i: 0, j: 1},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Times.Swap",
|
||||||
|
a: times{t2, t1},
|
||||||
|
args: args{i: 0, j: 1},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := tt.a.Less(tt.args.i, tt.args.j); got != tt.want {
|
||||||
|
t.Errorf("times.Less() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,20 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pborman/getopt/v2"
|
"github.com/pborman/getopt/v2"
|
||||||
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
|
||||||
"github.com/percona/pmgo"
|
"github.com/percona/pmgo"
|
||||||
|
|
||||||
mgo "gopkg.in/mgo.v2"
|
|
||||||
"gopkg.in/mgo.v2/dbtest"
|
"gopkg.in/mgo.v2/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,19 +22,6 @@ func TestMain(m *testing.M) {
|
|||||||
tempDir, _ := ioutil.TempDir("", "testing")
|
tempDir, _ := ioutil.TempDir("", "testing")
|
||||||
Server.SetPath(tempDir)
|
Server.SetPath(tempDir)
|
||||||
|
|
||||||
dat, err := ioutil.ReadFile("test/sample/system.profile.json")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("cannot load fixtures: %s", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var docs []proto.SystemProfile
|
|
||||||
err = json.Unmarshal(dat, &docs)
|
|
||||||
c := Server.Session().DB("samples").C("system_profile")
|
|
||||||
for _, doc := range docs {
|
|
||||||
c.Insert(doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
retCode := m.Run()
|
retCode := m.Run()
|
||||||
|
|
||||||
Server.Session().Close()
|
Server.Session().Close()
|
||||||
@@ -52,283 +34,6 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(retCode)
|
os.Exit(retCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalcStats(t *testing.T) {
|
|
||||||
it := Server.Session().DB("samples").C("system_profile").Find(nil).Sort("Ts").Iter()
|
|
||||||
data := getData(it, []docsFilter{})
|
|
||||||
s := calcStats(data[0].NScanned)
|
|
||||||
|
|
||||||
want := statistics{Pct: 0, Total: 159, Min: 79, Max: 80, Avg: 79.5, Pct95: 80, StdDev: 0.5, Median: 79.5}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(s, want) {
|
|
||||||
t.Errorf("error in calcStats: got:\n%#v\nwant:\n%#v\n", s, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
wantTotals := stat{
|
|
||||||
ID: "",
|
|
||||||
Fingerprint: "",
|
|
||||||
Namespace: "",
|
|
||||||
Query: map[string]interface{}(nil),
|
|
||||||
Count: 0,
|
|
||||||
TableScan: false,
|
|
||||||
NScanned: []float64{79, 80},
|
|
||||||
NReturned: []float64{79, 80},
|
|
||||||
QueryTime: []float64{27, 28},
|
|
||||||
ResponseLength: []float64{109, 110},
|
|
||||||
LockTime: nil,
|
|
||||||
BlockedTime: nil,
|
|
||||||
FirstSeen: time.Time{},
|
|
||||||
LastSeen: time.Time{},
|
|
||||||
}
|
|
||||||
|
|
||||||
totals := getTotals(data[0:1])
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(totals, wantTotals) {
|
|
||||||
t.Errorf("error in calcStats: got:\n%#v\nwant:\n:%#v\n", totals, wantTotals)
|
|
||||||
}
|
|
||||||
var wantTotalCount int = 2
|
|
||||||
var wantTotalScanned, wantTotalReturned, wantTotalQueryTime, wantTotalBytes float64 = 159, 159, 55, 219
|
|
||||||
|
|
||||||
totalCount, totalScanned, totalReturned, totalQueryTime, totalBytes := calcTotals(data[0:1])
|
|
||||||
|
|
||||||
if totalCount != wantTotalCount {
|
|
||||||
t.Errorf("invalid total count. Want %v, got %v\n", wantTotalCount, totalCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
if totalScanned != wantTotalScanned {
|
|
||||||
t.Errorf("invalid total count. Want %v, got %v\n", wantTotalScanned, totalScanned)
|
|
||||||
}
|
|
||||||
if totalReturned != wantTotalReturned {
|
|
||||||
t.Errorf("invalid total count. Want %v, got %v\n", wantTotalReturned, totalReturned)
|
|
||||||
}
|
|
||||||
if totalQueryTime != wantTotalQueryTime {
|
|
||||||
t.Errorf("invalid total count. Want %v, got %v\n", wantTotalQueryTime, totalQueryTime)
|
|
||||||
}
|
|
||||||
if totalBytes != wantTotalBytes {
|
|
||||||
t.Errorf("invalid total count. Want %v, got %v\n", wantTotalBytes, totalBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetData(t *testing.T) {
|
|
||||||
it := Server.Session().DB("samples").C("system_profile").Find(nil).Iter()
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
i iter
|
|
||||||
want []stat
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "test 1",
|
|
||||||
i: it,
|
|
||||||
want: []stat{
|
|
||||||
stat{
|
|
||||||
ID: "6c3fff4804febd156700a06f9a346162",
|
|
||||||
Operation: "query",
|
|
||||||
Fingerprint: "find,limit",
|
|
||||||
Namespace: "samples.col1",
|
|
||||||
Query: map[string]interface{}{"find": "col1", "limit": float64(2)},
|
|
||||||
Count: 2,
|
|
||||||
TableScan: false,
|
|
||||||
NScanned: []float64{79, 80},
|
|
||||||
NReturned: []float64{79, 80},
|
|
||||||
QueryTime: []float64{27, 28},
|
|
||||||
ResponseLength: []float64{109, 110},
|
|
||||||
LockTime: times(nil),
|
|
||||||
BlockedTime: times(nil),
|
|
||||||
FirstSeen: time.Date(2016, time.November, 8, 13, 46, 27, 0, time.UTC).Local(),
|
|
||||||
LastSeen: time.Date(2016, time.November, 8, 13, 46, 27, 0, time.UTC).Local(),
|
|
||||||
},
|
|
||||||
stat{
|
|
||||||
ID: "fdcea004122ddb225bc56de417391e25",
|
|
||||||
Operation: "query",
|
|
||||||
Fingerprint: "find",
|
|
||||||
Namespace: "samples.col1",
|
|
||||||
Query: map[string]interface{}{"find": "col1"},
|
|
||||||
Count: 8,
|
|
||||||
TableScan: false,
|
|
||||||
NScanned: []float64{71, 72, 73, 74, 75, 76, 77, 78},
|
|
||||||
NReturned: []float64{71, 72, 73, 74, 75, 76, 77, 78},
|
|
||||||
QueryTime: []float64{19, 20, 21, 22, 23, 24, 25, 26},
|
|
||||||
ResponseLength: []float64{101, 102, 103, 104, 105, 106, 107, 108},
|
|
||||||
LockTime: times(nil),
|
|
||||||
BlockedTime: times(nil),
|
|
||||||
FirstSeen: time.Date(2016, time.November, 8, 13, 46, 27, 0, time.UTC).Local(),
|
|
||||||
LastSeen: time.Date(2016, time.November, 8, 13, 46, 27, 0, time.UTC).Local(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got := getData(tt.i, []docsFilter{})
|
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("got\n%#v\nwant\n%#v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUptime(t *testing.T) {
|
|
||||||
|
|
||||||
session := pmgo.NewSessionManager(Server.Session())
|
|
||||||
time.Sleep(1500 * time.Millisecond)
|
|
||||||
if uptime(session) <= 0 {
|
|
||||||
t.Error("uptime is 0")
|
|
||||||
}
|
|
||||||
session.Close()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFingerprint(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
query map[string]interface{}
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
query: map[string]interface{}{"query": map[string]interface{}{}, "orderby": map[string]interface{}{"ts": -1}},
|
|
||||||
want: "orderby,query,ts",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
query: map[string]interface{}{"find": "system.profile", "filter": map[string]interface{}{}, "sort": map[string]interface{}{"$natural": 1}},
|
|
||||||
want: "$natural",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
|
|
||||||
query: map[string]interface{}{"collection": "system.profile", "batchSize": 0, "getMore": 18531768265},
|
|
||||||
want: "batchSize,collection,getMore",
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
Main test case:
|
|
||||||
Got Query field:
|
|
||||||
{
|
|
||||||
"filter": {
|
|
||||||
"aSampleDate":{
|
|
||||||
"$gte":1427846400000,
|
|
||||||
"$lte":1486511999999},
|
|
||||||
"brotherId":"25047dd6f52711e6b3c7c454",
|
|
||||||
"examined":true,
|
|
||||||
"sampleResponse.sampleScore.selectedScore":{
|
|
||||||
"$in":[5,4,3,2,1]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"find": "transModifiedTags",
|
|
||||||
"ntoreturn":10,
|
|
||||||
"projection":{
|
|
||||||
"$sortKey":{
|
|
||||||
"$meta":"sortKey"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shardVersion":[571230652140,"6f7dcd9af52711e6ad7cc454"],
|
|
||||||
"sort":{"aSampleDate":-1}
|
|
||||||
}
|
|
||||||
|
|
||||||
Want fingerprint:
|
|
||||||
aSampleDate,brotherId,examined,sampleResponse.sampleScore.selectedScore
|
|
||||||
|
|
||||||
Why?
|
|
||||||
1) It is MongoDb 3.2+ (has filter instead of $query)
|
|
||||||
2) From the "filter" map, we are removing all keys starting with $
|
|
||||||
3) The key 'aSampleDate' exists in the "sort" map but it is not in the "filter" keys
|
|
||||||
so it has been added to the final fingerprint
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
query: map[string]interface{}{"sort": map[string]interface{}{"aSampleDate": -1}, "filter": map[string]interface{}{"aSampleDate": map[string]interface{}{"$gte": 1.4278464e+12, "$lte": 1.486511999999e+12}, "brotherId": "25047dd6f52711e6b3c7c454", "examined": true, "sampleResponse.sampleScore.selectedScore": map[string]interface{}{"$in": []interface{}{5, 4, 3, 2, 1}}}, "find": "transModifiedTags", "ntoreturn": 10, "projection": map[string]interface{}{"$sortKey": map[string]interface{}{"$meta": "sortKey"}}, "shardVersion": []interface{}{5.7123065214e+11, "6f7dcd9af52711e6ad7cc454"}},
|
|
||||||
want: "aSampleDate,brotherId,examined,sampleResponse.sampleScore.selectedScore",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got, err := fingerprint(tt.query); got != tt.want || err != nil {
|
|
||||||
t.Errorf("fingerprint case #%d:\n got %v,\nwant %v\nerror: %v\n", i, got, tt.want, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimesLen(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
a times
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Times.Len",
|
|
||||||
a: []time.Time{time.Now()},
|
|
||||||
want: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := tt.a.Len(); got != tt.want {
|
|
||||||
t.Errorf("times.Len() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimesSwap(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
i int
|
|
||||||
j int
|
|
||||||
}
|
|
||||||
t1 := time.Now()
|
|
||||||
t2 := t1.Add(1 * time.Minute)
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
a times
|
|
||||||
args args
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Times.Swap",
|
|
||||||
a: times{t1, t2},
|
|
||||||
args: args{i: 0, j: 1},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
tt.a.Swap(tt.args.i, tt.args.j)
|
|
||||||
if tt.a[0] != t2 || tt.a[1] != t1 {
|
|
||||||
t.Errorf("%s has (%v, %v) want (%v, %v)", tt.name, tt.a[0], tt.a[1], t2, t1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimesLess(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
i int
|
|
||||||
j int
|
|
||||||
}
|
|
||||||
t1 := time.Now()
|
|
||||||
t2 := t1.Add(1 * time.Minute)
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
a times
|
|
||||||
args args
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Times.Swap",
|
|
||||||
a: times{t1, t2},
|
|
||||||
args: args{i: 0, j: 1},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Times.Swap",
|
|
||||||
a: times{t2, t1},
|
|
||||||
args: args{i: 0, j: 1},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := tt.a.Less(tt.args.i, tt.args.j); got != tt.want {
|
|
||||||
t.Errorf("times.Less() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsProfilerEnabled(t *testing.T) {
|
func TestIsProfilerEnabled(t *testing.T) {
|
||||||
mongoDSN := os.Getenv("PT_TEST_MONGODB_DSN")
|
mongoDSN := os.Getenv("PT_TEST_MONGODB_DSN")
|
||||||
if mongoDSN == "" {
|
if mongoDSN == "" {
|
||||||
@@ -336,7 +41,8 @@ func TestIsProfilerEnabled(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialer := pmgo.NewDialer()
|
dialer := pmgo.NewDialer()
|
||||||
di, _ := mgo.ParseURL(mongoDSN)
|
di, _ := pmgo.ParseURL(mongoDSN)
|
||||||
|
|
||||||
enabled, err := isProfilerEnabled(dialer, di)
|
enabled, err := isProfilerEnabled(dialer, di)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -365,13 +71,25 @@ func TestParseArgs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: []string{TOOLNAME, "zapp.brannigan.net:27018/samples", "--help"},
|
args: []string{TOOLNAME, "zapp.brannigan.net:27018/samples", "--help"},
|
||||||
|
want: nil,
|
||||||
|
//want: &options{
|
||||||
|
// Host: "zapp.brannigan.net:27018/samples",
|
||||||
|
// LogLevel: DEFAULT_LOGLEVEL,
|
||||||
|
// OrderBy: strings.Split(DEFAULT_ORDERBY, ","),
|
||||||
|
// SkipCollections: strings.Split(DEFAULT_SKIPCOLLECTIONS, ","),
|
||||||
|
// AuthDB: DEFAULT_AUTHDB,
|
||||||
|
// Help: true,
|
||||||
|
//},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{TOOLNAME, "zapp.brannigan.net:27018/samples"},
|
||||||
want: &options{
|
want: &options{
|
||||||
Host: "zapp.brannigan.net:27018/samples",
|
Host: "zapp.brannigan.net:27018/samples",
|
||||||
LogLevel: DEFAULT_LOGLEVEL,
|
LogLevel: DEFAULT_LOGLEVEL,
|
||||||
OrderBy: strings.Split(DEFAULT_ORDERBY, ","),
|
OrderBy: strings.Split(DEFAULT_ORDERBY, ","),
|
||||||
SkipCollections: strings.Split(DEFAULT_SKIPCOLLECTIONS, ","),
|
SkipCollections: strings.Split(DEFAULT_SKIPCOLLECTIONS, ","),
|
||||||
AuthDB: DEFAULT_AUTHDB,
|
AuthDB: DEFAULT_AUTHDB,
|
||||||
Help: true,
|
Help: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user