youtubebeat/vendor/github.com/elastic/beats/metricbeat/mb/mb_test.go

400 lines
9.8 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// +build !integration
package mb
import (
"testing"
"time"
"github.com/elastic/beats/libbeat/common"
"github.com/stretchr/testify/assert"
)
type testModule struct {
BaseModule
hostParser func(string) (HostData, error)
}
func (m testModule) ParseHost(host string) (HostData, error) {
return m.hostParser(host)
}
// EventFetcher
type testMetricSet struct {
BaseMetricSet
}
func (m *testMetricSet) Fetch() (common.MapStr, error) {
return nil, nil
}
// EventsFetcher
type testMetricSetEventsFetcher struct {
BaseMetricSet
}
func (m *testMetricSetEventsFetcher) Fetch() ([]common.MapStr, error) {
return nil, nil
}
// ReportingFetcher
type testMetricSetReportingFetcher struct {
BaseMetricSet
}
func (m *testMetricSetReportingFetcher) Fetch(r Reporter) {}
// PushMetricSet
type testPushMetricSet struct {
BaseMetricSet
}
func (m *testPushMetricSet) Run(r PushReporter) {}
func TestModuleConfig(t *testing.T) {
tests := []struct {
in interface{}
out ModuleConfig
err string
}{
{
in: map[string]interface{}{},
err: "missing required field accessing 'module'",
},
{
in: map[string]interface{}{
"module": "example",
"metricsets": []string{"test"},
},
out: ModuleConfig{
Module: "example",
MetricSets: []string{"test"},
Enabled: true,
Period: time.Second * 10,
Timeout: 0,
},
},
{
in: map[string]interface{}{
"module": "example",
"metricsets": []string{"test"},
"period": -1,
},
err: "negative value accessing 'period'",
},
{
in: map[string]interface{}{
"module": "example",
"metricsets": []string{"test"},
"timeout": -1,
},
err: "negative value accessing 'timeout'",
},
}
for i, test := range tests {
c, err := common.NewConfigFrom(test.in)
if err != nil {
t.Fatal(err)
}
unpackedConfig := DefaultModuleConfig()
err = c.Unpack(&unpackedConfig)
if err != nil && test.err == "" {
t.Errorf("unexpected error while unpacking in testcase %d: %v", i, err)
continue
}
if test.err != "" {
if err != nil {
assert.Contains(t, err.Error(), test.err, "testcase %d", i)
} else {
t.Errorf("expected error '%v' in testcase %d", test.err, i)
}
continue
}
assert.Equal(t, test.out, unpackedConfig)
}
}
// TestModuleConfigDefaults validates that the default values are not changed.
// Any changes to this test case are probably indicators of non-backwards
// compatible changes affect all modules (including community modules).
func TestModuleConfigDefaults(t *testing.T) {
c, err := common.NewConfigFrom(map[string]interface{}{
"module": "mymodule",
"metricsets": []string{"mymetricset"},
})
if err != nil {
t.Fatal(err)
}
mc := DefaultModuleConfig()
err = c.Unpack(&mc)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, true, mc.Enabled)
assert.Equal(t, time.Second*10, mc.Period)
assert.Equal(t, time.Second*0, mc.Timeout)
assert.Empty(t, mc.Hosts)
}
// TestNewModulesDuplicateHosts verifies that an error is returned by
// NewModules if any module configuration contains duplicate hosts.
func TestNewModulesDuplicateHosts(t *testing.T) {
r := newTestRegistry(t)
c := newConfig(t, map[string]interface{}{
"module": moduleName,
"metricsets": []string{metricSetName},
"hosts": []string{"a", "b", "a"},
})
_, _, err := NewModule(c, r)
assert.Error(t, err)
}
// TestNewModulesWithDefaultMetricSet verifies that the default MetricSet is
// instantiated when no metricsets are specified in the config.
func TestNewModulesWithDefaultMetricSet(t *testing.T) {
r := newTestRegistry(t, DefaultMetricSet())
c := newConfig(t, map[string]interface{}{
"module": moduleName,
})
_, metricSets, err := NewModule(c, r)
if err != nil {
t.Fatal(err)
}
if assert.Len(t, metricSets, 1) {
assert.Equal(t, metricSetName, metricSets[0].Name())
}
}
func TestNewModulesHostParser(t *testing.T) {
const (
name = "HostParser"
host = "example.com"
uri = "http://" + host
)
r := newTestRegistry(t)
factory := func(base BaseMetricSet) (MetricSet, error) {
return &testMetricSet{BaseMetricSet: base}, nil
}
hostParser := func(m Module, rawHost string) (HostData, error) {
return HostData{URI: uri, Host: host}, nil
}
if err := r.AddMetricSet(moduleName, name, factory, hostParser); err != nil {
t.Fatal(err)
}
t.Run("MetricSet without HostParser", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{metricSetName},
"hosts": []string{uri},
})
// The URI is passed through in the Host() and HostData().URI.
assert.Equal(t, uri, ms.Host())
assert.Equal(t, HostData{URI: uri}, ms.HostData())
})
t.Run("MetricSet with HostParser", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{name},
"hosts": []string{uri},
})
// The URI is passed through in the Host() and HostData().URI.
assert.Equal(t, host, ms.Host())
assert.Equal(t, HostData{URI: uri, Host: host}, ms.HostData())
})
}
func TestNewModulesMetricSetTypes(t *testing.T) {
r := newTestRegistry(t)
factory := func(base BaseMetricSet) (MetricSet, error) {
return &testMetricSet{base}, nil
}
name := "EventFetcher"
if err := r.AddMetricSet(moduleName, name, factory); err != nil {
t.Fatal(err)
}
t.Run(name+" MetricSet", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{name},
})
_, ok := ms.(EventFetcher)
assert.True(t, ok, name+" not implemented")
})
factory = func(base BaseMetricSet) (MetricSet, error) {
return &testMetricSetEventsFetcher{base}, nil
}
name = "EventsFetcher"
if err := r.AddMetricSet(moduleName, name, factory); err != nil {
t.Fatal(err)
}
t.Run(name+" MetricSet", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{name},
})
_, ok := ms.(EventsFetcher)
assert.True(t, ok, name+" not implemented")
})
factory = func(base BaseMetricSet) (MetricSet, error) {
return &testMetricSetReportingFetcher{base}, nil
}
name = "ReportingFetcher"
if err := r.AddMetricSet(moduleName, name, factory); err != nil {
t.Fatal(err)
}
t.Run(name+" MetricSet", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{name},
})
_, ok := ms.(ReportingMetricSet)
assert.True(t, ok, name+" not implemented")
})
factory = func(base BaseMetricSet) (MetricSet, error) {
return &testPushMetricSet{base}, nil
}
name = "Push"
if err := r.AddMetricSet(moduleName, name, factory); err != nil {
t.Fatal(err)
}
t.Run(name+" MetricSet", func(t *testing.T) {
ms := newTestMetricSet(t, r, map[string]interface{}{
"module": moduleName,
"metricsets": []string{name},
})
_, ok := ms.(PushMetricSet)
assert.True(t, ok, name+" not implemented")
})
}
// TestNewBaseModuleFromModuleConfigStruct tests the creation a new BaseModule.
func TestNewBaseModuleFromModuleConfigStruct(t *testing.T) {
moduleConf := DefaultModuleConfig()
moduleConf.Module = moduleName
moduleConf.MetricSets = []string{metricSetName}
c := newConfig(t, moduleConf)
baseModule, err := newBaseModuleFromConfig(c)
assert.NoError(t, err)
assert.Equal(t, moduleName, baseModule.Name())
assert.Equal(t, moduleName, baseModule.Config().Module)
assert.Equal(t, true, baseModule.Config().Enabled)
assert.Equal(t, time.Second*10, baseModule.Config().Period)
assert.Equal(t, time.Second*10, baseModule.Config().Timeout)
assert.Empty(t, baseModule.Config().Hosts)
}
func newTestRegistry(t testing.TB, metricSetOptions ...MetricSetOption) *Register {
r := NewRegister()
if err := r.AddModule(moduleName, DefaultModuleFactory); err != nil {
t.Fatal(err)
}
factory := func(base BaseMetricSet) (MetricSet, error) {
return &testMetricSet{base}, nil
}
if err := r.addMetricSet(moduleName, metricSetName, factory, metricSetOptions...); err != nil {
t.Fatal(err)
}
return r
}
func newTestMetricSet(t testing.TB, r *Register, config map[string]interface{}) MetricSet {
_, metricsets, err := NewModule(newConfig(t, config), r)
if err != nil {
t.Fatal(err)
}
if !assert.Len(t, metricsets, 1) {
assert.FailNow(t, "invalid number of metricsets")
}
return metricsets[0]
}
func newConfig(t testing.TB, moduleConfig interface{}) *common.Config {
config, err := common.NewConfigFrom(moduleConfig)
if err != nil {
t.Fatal(err)
}
return config
}
func TestModuleConfigQueryParams(t *testing.T) {
qp := QueryParams{
"stringKey": "value",
"intKey": 10,
"floatKey": 11.5,
"boolKey": true,
"nullKey": nil,
"arKey": []interface{}{1, 2},
}
res := qp.String()
expectedValues := []string{"stringKey=value", "intKey=10", "floatKey=11.5", "boolKey=true", "nullKey=", "arKey=1", "arKey=2"}
for _, expected := range expectedValues {
assert.Contains(t, res, expected)
}
assert.NotContains(t, res, "?")
assert.NotContains(t, res, "%")
assert.NotEqual(t, "&", res[0])
assert.NotEqual(t, "&", res[len(res)-1])
}