From b469b6cc848352154cf945dfa8ba7c27d374d31d Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Thu, 12 Jul 2018 17:26:01 +0200 Subject: [PATCH] Nested fields for all types in mapstriface of common.Schema --- .../common/schema/mapstriface/mapstriface.go | 24 +++--- .../schema/mapstriface/mapstriface_test.go | 79 +++++++++++++++++++ 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/libbeat/common/schema/mapstriface/mapstriface.go b/libbeat/common/schema/mapstriface/mapstriface.go index f43cc62e79eb..cda5c093ac9b 100644 --- a/libbeat/common/schema/mapstriface/mapstriface.go +++ b/libbeat/common/schema/mapstriface/mapstriface.go @@ -91,8 +91,8 @@ type ConvMap struct { // Map drills down in the data dictionary by using the key func (convMap ConvMap) Map(key string, event common.MapStr, data map[string]interface{}) multierror.Errors { - d, found := data[convMap.Key] - if !found { + d, err := common.MapStr(data).GetValue(convMap.Key) + if err != nil { err := schema.NewKeyNotFoundError(convMap.Key) err.Optional = convMap.Optional err.Required = convMap.Required @@ -130,8 +130,8 @@ func Dict(key string, s schema.Schema, opts ...DictSchemaOption) ConvMap { } func toStrFromNum(key string, data map[string]interface{}) (interface{}, error) { - emptyIface, exists := data[key] - if !exists { + emptyIface, err := common.MapStr(data).GetValue(key) + if err != nil { return "", schema.NewKeyNotFoundError(key) } switch emptyIface.(type) { @@ -184,8 +184,8 @@ func Ifc(key string, opts ...schema.SchemaOption) schema.Conv { } func toBool(key string, data map[string]interface{}) (interface{}, error) { - emptyIface, exists := data[key] - if !exists { + emptyIface, err := common.MapStr(data).GetValue(key) + if err != nil { return false, schema.NewKeyNotFoundError(key) } boolean, ok := emptyIface.(bool) @@ -202,8 +202,8 @@ func Bool(key string, opts ...schema.SchemaOption) schema.Conv { } func toInteger(key string, data map[string]interface{}) (interface{}, error) { - emptyIface, exists := data[key] - if !exists { + emptyIface, err := common.MapStr(data).GetValue(key) + if err != nil { return 0, schema.NewKeyNotFoundError(key) } switch emptyIface.(type) { @@ -238,8 +238,8 @@ func Float(key string, opts ...schema.SchemaOption) schema.Conv { } func toFloat(key string, data map[string]interface{}) (interface{}, error) { - emptyIface, exists := data[key] - if !exists { + emptyIface, err := common.MapStr(data).GetValue(key) + if err != nil { return 0.0, schema.NewKeyNotFoundError(key) } switch emptyIface.(type) { @@ -274,8 +274,8 @@ func Int(key string, opts ...schema.SchemaOption) schema.Conv { } func toTime(key string, data map[string]interface{}) (interface{}, error) { - emptyIface, exists := data[key] - if !exists { + emptyIface, err := common.MapStr(data).GetValue(key) + if err != nil { return common.Time(time.Unix(0, 0)), schema.NewKeyNotFoundError(key) } diff --git a/libbeat/common/schema/mapstriface/mapstriface_test.go b/libbeat/common/schema/mapstriface/mapstriface_test.go index 36905a6cd4f8..9bd53cb404d9 100644 --- a/libbeat/common/schema/mapstriface/mapstriface_test.go +++ b/libbeat/common/schema/mapstriface/mapstriface_test.go @@ -252,3 +252,82 @@ func TestFullFieldPathInErrors(t *testing.T) { } } } + +func TestNestedFieldPaths(t *testing.T) { + cases := []struct { + Description string + Input map[string]interface{} + Schema s.Schema + Expected common.MapStr + ExpectError bool + }{ + { + "nested values", + map[string]interface{}{ + "root": map[string]interface{}{ + "foo": "bar", + "float": 4.5, + "int": 4, + "bool": true, + }, + }, + s.Schema{ + "foo": Str("root.foo"), + "float": Float("root.float"), + "int": Int("root.int"), + "bool": Bool("root.bool"), + }, + common.MapStr{ + "foo": "bar", + "float": float64(4.5), + "int": int64(4), + "bool": true, + }, + false, + }, + { + "not really nested values, path contains dots", + map[string]interface{}{ + "root.foo": "bar", + }, + s.Schema{ + "foo": Str("root.foo"), + }, + common.MapStr{ + "foo": "bar", + }, + false, + }, + { + "nested dict", + map[string]interface{}{ + "root": map[string]interface{}{ + "dict": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + s.Schema{ + "dict": Dict("root.dict", s.Schema{ + "foo": Str("foo"), + }), + }, + common.MapStr{ + "dict": common.MapStr{ + "foo": "bar", + }, + }, + false, + }, + } + + for _, c := range cases { + event, err := c.Schema.Apply(c.Input) + if c.ExpectError { + assert.Error(t, err, c.Description) + } else { + assert.NoError(t, err, c.Description) + assert.Equal(t, c.Expected, event, c.Description) + } + } +}