checker-happydeliver/checker/provider_test.go

138 lines
3.7 KiB
Go

package checker
import (
"encoding/json"
"testing"
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
type fakeReportCtx struct {
data json.RawMessage
}
func (f fakeReportCtx) Data() json.RawMessage { return f.data }
func (fakeReportCtx) Related(sdk.ObservationKey) []sdk.RelatedObservation { return nil }
func (fakeReportCtx) States() []sdk.CheckState { return nil }
func TestProviderKey(t *testing.T) {
p := Provider()
if p.Key() != ObservationKeyHappyDeliver {
t.Errorf("Key = %q", p.Key())
}
}
func TestProviderImplementsMetricsReporter(t *testing.T) {
if _, ok := Provider().(sdk.CheckerMetricsReporter); !ok {
t.Fatal("provider should implement CheckerMetricsReporter")
}
}
func TestExtractMetrics(t *testing.T) {
d := HappyDeliverData{
Phase: "ok",
Scores: map[string]int{
SectionOverall: 88, SectionDNS: 90, SectionAuthentication: 70,
},
}
raw, _ := json.Marshal(d)
now := time.Now()
metrics, err := Provider().(sdk.CheckerMetricsReporter).ExtractMetrics(fakeReportCtx{data: raw}, now)
if err != nil {
t.Fatal(err)
}
if len(metrics) != 3 {
t.Fatalf("expected 3 metrics, got %d", len(metrics))
}
// Order must match AllSections (overall first).
if metrics[0].Labels["section"] != SectionOverall || metrics[0].Value != 88 {
t.Errorf("metrics[0] = %+v", metrics[0])
}
for _, m := range metrics {
if m.Name != "happydeliver_score" {
t.Errorf("name = %q", m.Name)
}
if m.Unit != "points" {
t.Errorf("unit = %q", m.Unit)
}
if !m.Timestamp.Equal(now) {
t.Errorf("ts = %v", m.Timestamp)
}
}
}
func TestExtractMetricsNoScores(t *testing.T) {
d := HappyDeliverData{Phase: "send", Error: "x"}
raw, _ := json.Marshal(d)
metrics, err := Provider().(sdk.CheckerMetricsReporter).ExtractMetrics(fakeReportCtx{data: raw}, time.Now())
if err != nil {
t.Fatal(err)
}
if metrics != nil {
t.Errorf("expected nil metrics, got %v", metrics)
}
}
func TestExtractMetricsBadPayload(t *testing.T) {
_, err := Provider().(sdk.CheckerMetricsReporter).ExtractMetrics(fakeReportCtx{data: []byte("garbage")}, time.Now())
if err == nil {
t.Fatal("expected error on bad JSON")
}
}
func TestDefinitionShape(t *testing.T) {
def := Definition()
if def.ID != "happydeliver" {
t.Errorf("ID = %q", def.ID)
}
if !def.Availability.ApplyToDomain {
t.Error("should apply to domain")
}
if !def.HasMetrics {
t.Error("HasMetrics should be true")
}
// Section rules + lifecycle rule.
if got, want := len(def.Rules), len(AllSections)+1; got != want {
t.Errorf("rule count = %d, want %d", got, want)
}
// Each section must have a corresponding rule named happydeliver.score.<section>.
have := map[string]bool{}
for _, r := range def.Rules {
have[r.Name()] = true
}
for _, s := range AllSections {
if !have["happydeliver.score."+s] {
t.Errorf("missing rule for section %q", s)
}
}
if !have["happydeliver.lifecycle"] {
t.Error("missing lifecycle rule")
}
if def.Interval == nil || def.Interval.Default != 7*24*time.Hour {
t.Errorf("interval = %+v", def.Interval)
}
}
func TestDefinitionBuildRulesInfo(t *testing.T) {
def := Definition()
def.BuildRulesInfo()
if len(def.RulesInfo) != len(def.Rules) {
t.Fatalf("RulesInfo len = %d, want %d", len(def.RulesInfo), len(def.Rules))
}
// Section rules expose Options(); the lifecycle rule does not.
var withOpts, withoutOpts int
for _, info := range def.RulesInfo {
if info.Options != nil {
withOpts++
} else {
withoutOpts++
}
}
if withOpts != len(AllSections) {
t.Errorf("rules-with-options = %d, want %d", withOpts, len(AllSections))
}
if withoutOpts != 1 {
t.Errorf("rules-without-options = %d, want 1 (lifecycle)", withoutOpts)
}
}