github.com/Jeffail/benthos/v3@v3.65.0/lib/config/config_test.go (about) 1 package config_test 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "reflect" 7 "strings" 8 "testing" 9 10 "github.com/Jeffail/benthos/v3/internal/docs" 11 "github.com/Jeffail/benthos/v3/lib/config" 12 "github.com/Jeffail/benthos/v3/lib/input" 13 "github.com/Jeffail/benthos/v3/lib/output" 14 "github.com/Jeffail/benthos/v3/lib/processor" 15 "github.com/Jeffail/gabs/v2" 16 "github.com/stretchr/testify/assert" 17 yaml "gopkg.in/yaml.v3" 18 19 _ "github.com/Jeffail/benthos/v3/public/components/all" 20 ) 21 22 func TestComponentExamples(t *testing.T) { 23 testComponent := func(componentType, typeName, title, conf string, deprecated bool) { 24 s := config.New() 25 dec := yaml.NewDecoder(bytes.NewReader([]byte(conf))) 26 dec.KnownFields(true) 27 assert.NoError(t, dec.Decode(&s), "%v:%v:%v", componentType, typeName, title) 28 29 lintCtx := docs.NewLintContext() 30 lintCtx.RejectDeprecated = !deprecated 31 lints, err := config.LintV2(lintCtx, []byte(conf)) 32 assert.NoError(t, err, "%v:%v:%v", componentType, typeName, title) 33 for _, lint := range lints { 34 t.Errorf("%v %v:%v:%v", lint, componentType, typeName, title) 35 } 36 37 type confAlias config.Type 38 sAliased := confAlias(config.New()) 39 dec = yaml.NewDecoder(bytes.NewReader([]byte(conf))) 40 dec.KnownFields(true) 41 assert.NoError(t, dec.Decode(&sAliased), "%v:%v:%v", componentType, typeName, title) 42 } 43 44 for typeName, ctor := range input.Constructors { 45 for _, example := range ctor.Examples { 46 testComponent("input", typeName, example.Title, example.Config, ctor.Status == docs.StatusDeprecated) 47 } 48 } 49 for typeName, ctor := range processor.Constructors { 50 for _, example := range ctor.Examples { 51 testComponent("processor", typeName, example.Title, example.Config, ctor.Status == docs.StatusDeprecated) 52 } 53 } 54 for typeName, ctor := range output.Constructors { 55 for _, example := range ctor.Examples { 56 testComponent("output", typeName, example.Title, example.Config, ctor.Status == docs.StatusDeprecated) 57 } 58 } 59 } 60 61 func CheckTagsOfType(v reflect.Type, checkedTypes map[string]struct{}, t *testing.T) { 62 tPath := v.PkgPath() + "." + v.Name() 63 if _, exists := checkedTypes[tPath]; len(v.PkgPath()) > 0 && exists { 64 return 65 } 66 checkedTypes[tPath] = struct{}{} 67 68 switch v.Kind() { 69 case reflect.Slice: 70 CheckTagsOfType(v.Elem(), checkedTypes, t) 71 case reflect.Map: 72 CheckTagsOfType(v.Elem(), checkedTypes, t) 73 case reflect.Struct: 74 for i := 0; i < v.NumField(); i++ { 75 field := v.Field(i) 76 jTag := field.Tag.Get("json") 77 yTag := field.Tag.Get("yaml") 78 79 if len(field.PkgPath) > 0 { 80 continue 81 } 82 83 if yTag == "" { 84 t.Errorf("Empty field '%v' tag in type %v", field.Name, tPath) 85 } 86 87 if strings.ToLower(yTag) != yTag { 88 t.Errorf("Non-lower case field '%v' tag in type %v: %v", field.Name, tPath, yTag) 89 } 90 91 if jTag != yTag { 92 t.Errorf("Mismatched field '%v' config tags in type %v: json(%v) != yaml(%v)", field.Name, tPath, jTag, yTag) 93 } 94 95 CheckTagsOfType(field.Type, checkedTypes, t) 96 } 97 } 98 } 99 100 func TestConfigTags(t *testing.T) { 101 v := reflect.TypeOf(config.New()) 102 103 checkedTypes := map[string]struct{}{} 104 CheckTagsOfType(v, checkedTypes, t) 105 } 106 107 func TestExampleGen(t *testing.T) { 108 conf := config.New() 109 config.AddExamples(&conf, "files", "memory", "jmespath", "file") 110 111 jBytes, err := json.Marshal(conf) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 gObj, err := gabs.ParseJSON(jBytes) 117 if err != nil { 118 t.Fatal(err) 119 } 120 121 if exp, act := `"files"`, gObj.Path("input.type").String(); exp != act { 122 t.Errorf("Unexpected conf value: %v != %v", act, exp) 123 } 124 125 if exp, act := `"memory"`, gObj.Path("buffer.type").String(); exp != act { 126 t.Errorf("Unexpected conf value: %v != %v", act, exp) 127 } 128 129 if exp, act := `["jmespath","filter_parts"]`, gObj.Path("pipeline.processors.*.type").String(); exp != act { 130 t.Errorf("Unexpected conf value: %v != %v", act, exp) 131 } 132 133 if exp, act := `["text","jmespath"]`, gObj.Path("pipeline.processors.*.filter_parts.type").String(); exp != act { 134 t.Errorf("Unexpected conf value: %v != %v", act, exp) 135 } 136 137 if exp, act := `"file"`, gObj.Path("output.type").String(); exp != act { 138 t.Errorf("Unexpected conf value: %v != %v", act, exp) 139 } 140 }