Skip to content

Commit bac2f83

Browse files
authored
Bump test coverage (#53)
* Test graph output * Add entry.Read tests * Add tests for entry.Parent and entry.Child * Add parser_regex tests * Add tests for errors * Add test for google cloud output * Add tests for TCP input plugin * Add TCP and UDP tests * Run tests in parallel and decrease polling rate for performance * Add basic router test * Add simple tests for generate_input * Add coverpkg argument to tests * Add basic syslog tests * Add basic time parser and noop tests * Move credentials parsing into Start() * Remove traces of mapstructure * Add basic timestamp plugin tests * Log unexpected message
1 parent dc63f99 commit bac2f83

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1366
-830
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
- run:
4040
name: Unit tests
4141
command: |
42-
go test -race -v -coverprofile=c.out ./...
42+
go test -race -v -coverprofile=c.out -coverpkg ./... ./...
4343
./cc-test-reporter after-build --coverage-input-type gocov -p github.com/bluemedora/bplogagent/
4444
4545
test-macos:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
dev/*
22
.DS_Store
3-
tmp/*
3+
tmp/*
4+
coverage.txt

commands/graph.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ type GraphFlags struct {
1616
*RootFlags
1717
}
1818

19-
func runGraph(command *cobra.Command, args []string, flags *GraphFlags) error {
19+
func NewGraphCommand(rootFlags *RootFlags) *cobra.Command {
20+
return &cobra.Command{
21+
Use: "graph",
22+
Args: cobra.NoArgs,
23+
Short: "Export a dot-formatted representation of the plugin graph",
24+
Run: func(command *cobra.Command, args []string) { runGraph(command, args, rootFlags) },
25+
}
26+
}
27+
28+
func runGraph(command *cobra.Command, args []string, flags *RootFlags) error {
2029
var logger *zap.SugaredLogger
2130
if flags.Debug {
2231
logger = newDefaultLoggerAt(zapcore.DebugLevel)

commands/graph_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package commands
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
func ExampleGraph() {
10+
config := []byte(`
11+
plugins:
12+
- id: generate
13+
type: generate_input
14+
output: json_parser
15+
record:
16+
test: value
17+
18+
- id: json_parser
19+
type: json_parser
20+
output: google_cloud
21+
22+
- id: google_cloud
23+
project_id: testproject
24+
type: google_cloud_output
25+
`)
26+
tempDir, err := ioutil.TempDir("", "")
27+
if err != nil {
28+
panic(err)
29+
}
30+
defer os.RemoveAll(tempDir)
31+
32+
configPath := filepath.Join(tempDir, "config.yaml")
33+
err = ioutil.WriteFile(configPath, config, 0666)
34+
if err != nil {
35+
panic(err)
36+
}
37+
38+
rootFlags := &RootFlags{
39+
ConfigFiles: []string{configPath},
40+
}
41+
graphCmd := NewGraphCommand(rootFlags)
42+
graphCmd.Execute()
43+
44+
// Output:
45+
// strict digraph G {
46+
// // Node definitions.
47+
// generate;
48+
// json_parser;
49+
// google_cloud;
50+
//
51+
// // Edge definitions.
52+
// generate -> json_parser;
53+
// json_parser -> google_cloud;
54+
// }
55+
56+
}

commands/root.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,7 @@ func NewRootCmd() *cobra.Command {
5858
rootFlagSet.DurationVar(&rootFlags.MemProfileDelay, "mem_profile_delay", 10*time.Second, "time to wait before writing a memory profile")
5959
rootFlagSet.MarkHidden("mem_profile_delay")
6060

61-
graphFlags := &GraphFlags{
62-
RootFlags: rootFlags,
63-
}
64-
65-
graph := &cobra.Command{
66-
Use: "graph",
67-
Args: cobra.NoArgs,
68-
Short: "Export a dot-formatted representation of the plugin graph",
69-
Run: func(command *cobra.Command, args []string) { runGraph(command, args, graphFlags) },
70-
}
71-
61+
graph := NewGraphCommand(rootFlags)
7262
root.AddCommand(graph)
7363

7464
return root

config/config.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
)
1111

1212
type Config struct {
13-
Plugins []plugin.Config `mapstructure:"plugins" json:"plugins" yaml:"plugins"`
14-
DatabaseFile string `mapstructure:"database_file" json:"database_file,omitempty" yaml:"database_file,omitempty"`
13+
Plugins []plugin.Config `json:"plugins" yaml:"plugins"`
14+
DatabaseFile string `json:"database_file,omitempty" yaml:"database_file,omitempty"`
1515
}
1616

1717
func NewConfig() *Config {
@@ -20,8 +20,6 @@ func NewConfig() *Config {
2020
}
2121
}
2222

23-
var DecodeHookFunc = plugin.ConfigDecoder
24-
2523
func ReadConfigsFromGlobs(globs []string) (*Config, error) {
2624
paths := make([]string, 0, len(globs))
2725
for _, glob := range globs {

config/config_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,35 +244,30 @@ plugins:
244244
globs []string
245245
expectedPluginIDs []string
246246
expectedDatabaseFile string
247-
expectedError require.ErrorAssertionFunc
248247
}{
249248
{
250249
"multiple inputs",
251250
[]string{"file1", "file2", "output1"},
252251
[]string{"fileinput1", "fileinput2", "output1"},
253252
"test2.db",
254-
require.NoError,
255253
},
256254
{
257255
"single input",
258256
[]string{"file1", "output1"},
259257
[]string{"fileinput1", "output1"},
260258
"test1.db",
261-
require.NoError,
262259
},
263260
{
264261
"globbed inputs",
265262
[]string{"file*", "output1"},
266263
[]string{"fileinput1", "fileinput2", "output1"},
267264
"test2.db", // because glob returns in lexicographical order
268-
require.NoError,
269265
},
270266
{
271267
"globbed all",
272268
[]string{"*"},
273269
[]string{"fileinput1", "fileinput2", "output1"},
274270
"test2.db", // because glob returns in lexicographical order
275-
require.NoError,
276271
},
277272
}
278273

@@ -294,7 +289,7 @@ plugins:
294289
globs[i] = filepath.Join(dir, glob)
295290
}
296291
cfg, err := ReadConfigsFromGlobs(globs)
297-
tc.expectedError(t, err)
292+
require.NoError(t, err)
298293

299294
// Pull out the plugin IDs from the unmarshaled plugins
300295
pluginIDs := make([]string, len(cfg.Plugins))
@@ -306,5 +301,4 @@ plugins:
306301
require.ElementsMatch(t, tc.expectedPluginIDs, pluginIDs)
307302
})
308303
}
309-
310304
}

entry/entry_test.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,115 @@
11
package entry
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestRead(t *testing.T) {
10+
testEntry := &Entry{
11+
Record: map[string]interface{}{
12+
"string_field": "string_val",
13+
"map_string_interface_field": map[string]interface{}{
14+
"nested": "interface_val",
15+
},
16+
"map_string_interface_nonstring_field": map[string]interface{}{
17+
"nested": 111,
18+
},
19+
"map_string_string_field": map[string]string{
20+
"nested": "string_val",
21+
},
22+
"map_interface_interface_field": map[interface{}]interface{}{
23+
"nested": "interface_val",
24+
},
25+
"map_interface_interface_nonstring_key_field": map[interface{}]interface{}{
26+
100: "interface_val",
27+
},
28+
"map_interface_interface_nonstring_value_field": map[interface{}]interface{}{
29+
"nested": 100,
30+
},
31+
},
32+
}
33+
34+
t.Run("field not exist error", func(t *testing.T) {
35+
var s string
36+
err := testEntry.Read(Field{[]string{"nonexistant_field"}}, &s)
37+
require.Error(t, err)
38+
})
39+
40+
t.Run("unsupported type error", func(t *testing.T) {
41+
var s **string
42+
err := testEntry.Read(Field{[]string{"string_field"}}, &s)
43+
require.Error(t, err)
44+
})
45+
46+
t.Run("string", func(t *testing.T) {
47+
var s string
48+
err := testEntry.Read(Field{[]string{"string_field"}}, &s)
49+
require.NoError(t, err)
50+
51+
require.Equal(t, "string_val", s)
52+
})
53+
54+
t.Run("string error", func(t *testing.T) {
55+
var s string
56+
err := testEntry.Read(Field{[]string{"map_string_interface_field"}}, &s)
57+
require.Error(t, err)
58+
})
59+
60+
t.Run("map[string]interface{}", func(t *testing.T) {
61+
var m map[string]interface{}
62+
err := testEntry.Read(Field{[]string{"map_string_interface_field"}}, &m)
63+
require.NoError(t, err)
64+
65+
require.Equal(t, map[string]interface{}{"nested": "interface_val"}, m)
66+
})
67+
68+
t.Run("map[string]interface{} error", func(t *testing.T) {
69+
var m map[string]interface{}
70+
err := testEntry.Read(Field{[]string{"string_field"}}, &m)
71+
require.Error(t, err)
72+
})
73+
74+
t.Run("map[string]string from map[string]interface{}", func(t *testing.T) {
75+
var m map[string]string
76+
err := testEntry.Read(Field{[]string{"map_string_interface_field"}}, &m)
77+
require.NoError(t, err)
78+
79+
require.Equal(t, map[string]string{"nested": "interface_val"}, m)
80+
})
81+
82+
t.Run("map[string]string from map[string]interface{} err", func(t *testing.T) {
83+
var m map[string]string
84+
err := testEntry.Read(Field{[]string{"map_string_interface_nonstring_field"}}, &m)
85+
require.Error(t, err)
86+
})
87+
88+
t.Run("map[string]string from map[interface{}]interface{}", func(t *testing.T) {
89+
var m map[string]string
90+
err := testEntry.Read(Field{[]string{"map_interface_interface_field"}}, &m)
91+
require.NoError(t, err)
92+
93+
require.Equal(t, map[string]string{"nested": "interface_val"}, m)
94+
})
95+
96+
t.Run("map[string]string from map[interface{}]interface{} nonstring key error", func(t *testing.T) {
97+
var m map[string]string
98+
err := testEntry.Read(Field{[]string{"map_interface_interface_nonstring_key_field"}}, &m)
99+
require.Error(t, err)
100+
})
101+
102+
t.Run("map[string]string from map[interface{}]interface{} nonstring value error", func(t *testing.T) {
103+
var m map[string]string
104+
err := testEntry.Read(Field{[]string{"map_interface_interface_nonstring_value_field"}}, &m)
105+
require.Error(t, err)
106+
})
107+
108+
t.Run("interface{} from any", func(t *testing.T) {
109+
var i interface{}
110+
err := testEntry.Read(Field{[]string{"map_interface_interface_field"}}, &i)
111+
require.NoError(t, err)
112+
113+
require.Equal(t, map[interface{}]interface{}{"nested": "interface_val"}, i)
114+
})
115+
}

entry/field.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ package entry
33
import (
44
"encoding/json"
55
"fmt"
6-
"reflect"
76
"strings"
8-
9-
"github.com/bluemedora/bplogagent/errors"
10-
"github.com/mitchellh/mapstructure"
117
)
128

139
// Field represents a potential field on an entry's record.
@@ -229,19 +225,3 @@ func NewField(keys ...string) Field {
229225
Keys: keys,
230226
}
231227
}
232-
233-
// FieldDecoder is a custom decoder hook used by mapstructure to decode fields.
234-
var FieldDecoder mapstructure.DecodeHookFunc = func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
235-
if t.String() != "entry.Field" {
236-
return data, nil
237-
}
238-
239-
if reflect.TypeOf(string("")) == f {
240-
return fromJSONDot(data.(string)), nil
241-
}
242-
243-
return nil, errors.NewError(
244-
"failed to unmarshal field from type",
245-
"ensure that all fields are encoded as strings",
246-
"type", f.String())
247-
}

0 commit comments

Comments
 (0)