Skip to content

Commit

Permalink
Package api: Implement ValueList.Check().
Browse files Browse the repository at this point in the history
This new function does a sanity check on a ValueList, e.g. checking that
the Host field is set and that the number of values and DS names match.
  • Loading branch information
octo committed May 12, 2020
1 parent a3b6e91 commit 02bda99
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
43 changes: 43 additions & 0 deletions api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api // import "collectd.org/api"

import (
"context"
"errors"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -104,6 +105,48 @@ func (vl *ValueList) DSName(index int) string {
return "value"
}

// Check does a sanity check on vl and returns any errors it finds.
func (vl *ValueList) Check() error {
var err error

if vl.Host == "" {
err = multierr.Append(err, errors.New("Host is unset"))
}
if vl.Plugin == "" {
err = multierr.Append(err, errors.New("Plugin is unset"))
}
if strings.ContainsRune(vl.Plugin, '-') {
err = multierr.Append(err, errors.New("Plugin contains '-'"))
}
if vl.Type == "" {
err = multierr.Append(err, errors.New("Type is unset"))
}
if strings.ContainsRune(vl.Type, '-') {
err = multierr.Append(err, errors.New("Type contains '-'"))
}
if vl.Interval == 0 {
err = multierr.Append(err, errors.New("Interval is unset"))
}
if len(vl.Values) == 0 {
err = multierr.Append(err, errors.New("Values is unset"))
}
if n, v := len(vl.DSNames), len(vl.Values); n != 0 && v != 0 && n != v {
err = multierr.Append(err, fmt.Errorf("number of values (%d) and number of DS names (%d) don't match", v, n))
}

nameCount := make(map[string]int)
for _, name := range vl.DSNames {
nameCount[name] = nameCount[name] + 1
}
for name, count := range nameCount {
if count != 1 {
err = multierr.Append(err, fmt.Errorf("data source name %q is not unique", name))
}
}

return err
}

// Clone returns a copy of vl.
// Unfortunately, many functions expect a pointer to a value list. If the
// original value list must not be modified, it may be necessary to create and
Expand Down
138 changes: 138 additions & 0 deletions api/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"sync"
"testing"
"time"

"collectd.org/api"
"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -210,3 +211,140 @@ func TestFanout(t *testing.T) {
})
}
}

func TestValueList_Check(t *testing.T) {
baseVL := api.ValueList{
Identifier: api.Identifier{
Host: "example.com",
Plugin: "TestValueList_Check",
Type: "gauge",
},
Time: time.Unix(1589283551, 0),
Interval: 10 * time.Second,
Values: []api.Value{api.Gauge(42)},
DSNames: []string{"value"},
}

cases := []struct {
title string
modify func(vl *api.ValueList)
wantErr bool
}{
{
title: "success",
},
{
title: "without host",
modify: func(vl *api.ValueList) {
vl.Host = ""
},
wantErr: true,
},
{
title: "host contains hyphen",
modify: func(vl *api.ValueList) {
vl.Host = "example-host.com"
},
},
{
title: "without plugin",
modify: func(vl *api.ValueList) {
vl.Plugin = ""
},
wantErr: true,
},
{
title: "plugin contains hyphen",
modify: func(vl *api.ValueList) {
vl.Plugin = "TestValueList-Check"
},
wantErr: true,
},
{
title: "without type",
modify: func(vl *api.ValueList) {
vl.Type = ""
},
wantErr: true,
},
{
title: "type contains hyphen",
modify: func(vl *api.ValueList) {
vl.Type = "http-request"
},
wantErr: true,
},
{
title: "without time",
modify: func(vl *api.ValueList) {
vl.Time = time.Time{}
},
},
{
title: "without interval",
modify: func(vl *api.ValueList) {
vl.Interval = 0
},
wantErr: true,
},
{
title: "without values",
modify: func(vl *api.ValueList) {
vl.Values = nil
},
wantErr: true,
},
{
title: "surplus values",
modify: func(vl *api.ValueList) {
vl.Values = []api.Value{api.Gauge(1), api.Gauge(2)}
},
wantErr: true,
},
{
title: "without dsnames",
modify: func(vl *api.ValueList) {
vl.DSNames = nil
},
},
{
title: "surplus dsnames",
modify: func(vl *api.ValueList) {
vl.DSNames = []string{"rx", "tx"}
},
wantErr: true,
},
{
title: "multiple values",
modify: func(vl *api.ValueList) {
vl.Type = "if_octets"
vl.Values = []api.Value{api.Derive(0), api.Derive(0)}
vl.DSNames = []string{"rx", "tx"}
},
},
{
title: "ds name not unique",
modify: func(vl *api.ValueList) {
vl.Type = "if_octets"
vl.Values = []api.Value{api.Derive(0), api.Derive(0)}
vl.DSNames = []string{"value", "value"}
},
wantErr: true,
},
}

for _, tc := range cases {
t.Run(tc.title, func(t *testing.T) {
vl := baseVL.Clone()
if tc.modify != nil {
tc.modify(vl)
}

err := vl.Check()
if gotErr := err != nil; gotErr != tc.wantErr {
t.Errorf("%#v.Check() = %v, want error %v", vl, err, tc.wantErr)

}
})
}
}

0 comments on commit 02bda99

Please sign in to comment.