common/stats/verify_stats.go (102 lines of code) (raw):
package stats
import (
"bytes"
"fmt"
"strings"
"testing"
log "github.com/sirupsen/logrus"
)
/*
Utilities for validating the stats registry contents
*/
/*
add new Checker functions here as needed
*/
type RuleChecker struct {
name string
checker func(interface{}, interface{}) bool
}
func nilCheck(a, b interface{}) (nilFound, eqValues bool) {
nilFound = false
if b == nil && a == nil {
nilFound = true
eqValues = true
} else if b == nil || a == nil {
nilFound = true
eqValues = false
}
return
}
/*
errors if a is not float64, returns true if a == b
*/
func floatEqTest(a, b interface{}) bool {
if nilFound, eqValue := nilCheck(a, b); nilFound {
return eqValue
}
aflt := a.(float64)
bflt := b.(float64)
return aflt == bflt
}
var FloatEqTest = RuleChecker{name: "floatEqTest", checker: floatEqTest}
/*
errors if a is not float64, returns true if a > b
*/
func floatGTTest(a, b interface{}) bool {
if nilFound, eqValue := nilCheck(a, b); nilFound {
return eqValue
}
aflt := a.(float64)
bflt := b.(float64)
return aflt > bflt
}
var FloatGTTest = RuleChecker{name: "floatGTTest", checker: floatGTTest}
/*
errors if a is not int64, returns true if a == b
*/
func int64EqTest(a, b interface{}) bool {
if nilFound, eqValue := nilCheck(a, b); nilFound {
return eqValue
}
aint := a.(int64)
bint := b.(int)
return aint == int64(bint)
}
var Int64EqTest = RuleChecker{name: "IntEqTest", checker: int64EqTest}
/*
errors if a is not int64, returns true if a > b
*/
func int64GTTest(a, b interface{}) bool {
if nilFound, eqValue := nilCheck(a, b); nilFound {
return eqValue
}
aint := a.(int64)
bint := b.(int)
return aint > int64(bint)
}
var Int64GTTest = RuleChecker{name: "IntGTTest", checker: int64GTTest}
func doesNotExistTest(a, b interface{}) bool {
return a == nil
}
var DoesNotExistTest = RuleChecker{name: "NotExistCheck", checker: doesNotExistTest}
/*
defines the condition checker to use to validate the measurement. Each Checker(a, b) implementation
will expect a to be the 'got' value and b to be the 'expected' value.
*/
type Rule struct {
Checker RuleChecker
Value interface{}
}
/*
Verify that the stats registry object contains values for the keys in the contains map parameter and that
each entry conforms to the rule (condition) associated with that key.
*/
func StatsOk(tag string, statsRegistry StatsRegistry, t *testing.T, contains map[string]Rule) bool {
asFinagleRegistry, ok := statsRegistry.(*finagleStatsRegistry)
statsOk := true
var msg bytes.Buffer
msg.WriteString(tag)
msg.WriteString(":stats registry error:\n")
if ok {
asJson := asFinagleRegistry.MarshalAll()
for key, rule := range contains {
gotValue, _ := asJson[key]
if !rule.Checker.checker(gotValue, rule.Value) {
if strings.Compare(rule.Checker.name, DoesNotExistTest.name) == 0 {
statsOk = false
ruleMsg := fmt.Sprintf("%s: found stat entry when there should not be one", key)
msg.WriteString(fmt.Sprintln(ruleMsg))
} else {
statsOk = false
ruleMsg := fmt.Sprintf("\n%s: got %v, expected to pass %s with %v", key, gotValue, rule.Checker.name, rule.Value)
msg.WriteString(fmt.Sprintln(ruleMsg))
}
}
}
if !statsOk {
fmt.Println(msg.String())
PPrintStats(tag, asFinagleRegistry)
}
}
return statsOk
}
func PPrintStats(tag string, statsRegistry StatsRegistry) {
log.Infof("%s: Stats Registry:\n", tag)
asFinagleRegistry, _ := statsRegistry.(*finagleStatsRegistry)
regBytes, _ := asFinagleRegistry.MarshalJSONPretty()
log.Printf("%s\n", regBytes)
}