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  }