Skip to content

Commit

Permalink
Merge pull request #22 from goreflect/issue_8
Browse files Browse the repository at this point in the history
Issue 8 Resolved
  • Loading branch information
artemkaxboy committed Apr 9, 2020
2 parents 7a73cb8 + a143687 commit ceaad54
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 39 deletions.
10 changes: 5 additions & 5 deletions lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ func Test_getValueFromEnvironment(t *testing.T) {
os.Setenv("myField4", "12.2")
os.Setenv("myField5", "true,false,true")
defer func() {
os.Remove("myField1")
os.Remove("myField2")
os.Remove("myField3")
os.Remove("myField4")
os.Remove("myField5")
os.Unsetenv("myField1")
os.Unsetenv("myField2")
os.Unsetenv("myField3")
os.Unsetenv("myField4")
os.Unsetenv("myField5")
}()
myStruct, err := ConfigureSmart(&EnvStruct{}, "")
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions middlewares/empty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package middlewares

func emptyTagValue(tagValue string) bool {
return tagValue == ""
}
14 changes: 14 additions & 0 deletions middlewares/kernel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package middlewares

import "errors"

/*
ExecutorMiddlewaresByTagValue - entry point for all middlewares
TODO: increase by tagType
*/
func ExecutorMiddlewaresByTagValue(tagValue string, tagType string) error {
if emptyTagValue(tagValue) {
return errors.New("tagvalue can not be empty! ")
}
return nil
}
24 changes: 21 additions & 3 deletions pipeline/default_func.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package pipeline

import (
"errors"
"fmt"
"reflect"

"github.com/goreflect/gostructor/converters"
"github.com/goreflect/gostructor/infra"
"github.com/goreflect/gostructor/middlewares"
"github.com/goreflect/gostructor/tags"
"github.com/goreflect/gostructor/tools"
)

/*
Expand All @@ -18,13 +22,27 @@ GetComplexType - get slices, maps, arrays or anything else hard types
*/
func (config DefaultConfig) GetComplexType(context *structContext) infra.GoStructorValue {
fmt.Println("Level: Debug. Message: default values sources start")
return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("getComplexType not implemented for default configuring"))
valueIndirect := reflect.Indirect(context.Value)
value := context.StructField.Tag.Get(tags.TagDefault)
if err := middlewares.ExecutorMiddlewaresByTagValue(value, tags.TagDefault); err != nil {
return infra.NewGoStructorNoValue(context.Value, err)
}
array, err := tools.ConvertStringIntoArray(value, tools.ConfigureConverts{Separator: tools.COMMA})
if err != nil {
return infra.NewGoStructorNoValue(context.Value, err)
}
return converters.ConvertBetweenComplexTypes(reflect.ValueOf(array), valueIndirect)
}

/*
GetBaseType - get base type from default values.
*/
func (config DefaultConfig) GetBaseType(context *structContext) infra.GoStructorValue {
fmt.Println("Level: Debug. Message: default values sources start")
return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("getBaseType not implemented for default configuring"))
valueIndirect := reflect.Indirect(context.Value)
value := context.StructField.Tag.Get(tags.TagDefault)
if err := middlewares.ExecutorMiddlewaresByTagValue(value, tags.TagDefault); err != nil {
return infra.NewGoStructorNoValue(context.Value, err)
}
return converters.ConvertBetweenPrimitiveTypes(reflect.ValueOf(value), valueIndirect)
}
155 changes: 155 additions & 0 deletions pipeline/default_func_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package pipeline

import (
"errors"
"reflect"
"testing"

"github.com/goreflect/gostructor/infra"
)

func TestDefaultConfig_GetBaseType(t *testing.T) {
strct := struct {
field1 int8 `cf_default:"5"`
}{}
fieldType := reflect.ValueOf(strct).Type().Field(0)
fieldValue := reflect.ValueOf(strct).Field(0)
type args struct {
context *structContext
}
tests := []struct {
name string
config DefaultConfig
args args
want infra.GoStructorValue
}{
{
name: "check while configuring base type int8",
args: args{
context: &structContext{
Value: fieldValue,
StructField: fieldType,
},
},
want: infra.NewGoStructorTrueValue(reflect.ValueOf(int8(5))),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig{}
if got := config.GetBaseType(tt.args.context); !reflect.DeepEqual(got.Value, tt.want.Value) {
t.Errorf("DefaultConfig.GetBaseType() = %v, want %v", got, tt.want)
}
})
}
}

func TestDefaultConfig_GetBaseTypeFaield(t *testing.T) {
strct := struct {
field1 int8 `cf_default:""`
}{}
fieldType := reflect.ValueOf(strct).Type().Field(0)
fieldValue := reflect.ValueOf(strct).Field(0)
type args struct {
context *structContext
}
tests := []struct {
name string
config DefaultConfig
args args
want infra.GoStructorValue
}{
{
name: "check while configuring empty tag Value field",
args: args{
context: &structContext{
Value: fieldValue,
StructField: fieldType,
},
},
want: infra.NewGoStructorNoValue(fieldValue, errors.New("wrong format inside the tag")),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig{}
if got := config.GetBaseType(tt.args.context); !reflect.DeepEqual(got.Value, tt.want.Value) {
t.Errorf("DefaultConfig.GetBaseType() = %v, want %v", got, tt.want)
}
})
}
}

func TestDefaultConfig_GetComplexType(t *testing.T) {
strct := struct {
field []int8 `cf_default:"12,2,45,16"`
}{}
fieldType := reflect.ValueOf(strct).Type().Field(0)
fieldValue := reflect.ValueOf(strct).Field(0)
type args struct {
context *structContext
}
tests := []struct {
name string
config DefaultConfig
args args
want infra.GoStructorValue
}{
{
name: "get slice from default tag",
config: DefaultConfig{},
args: args{
context: &structContext{
Value: fieldValue,
StructField: fieldType,
},
},
want: infra.NewGoStructorTrueValue(reflect.ValueOf([]int8{12, 2, 45, 16})),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig{}
if got := config.GetComplexType(tt.args.context); !reflect.DeepEqual(got.Value.Interface(), tt.want.Value.Interface()) {
t.Errorf("DefaultConfig.GetComplexType() = %v, want %v", got, tt.want)
}
})
}
}

func TestDefaultConfig_GetComplexTypeNotImlemented(t *testing.T) {
strct := struct {
field map[string]string `cf_default:"12:12sda,51:5sda"`
}{}
fieldType := reflect.ValueOf(strct).Type().Field(0)
fieldValue := reflect.ValueOf(strct).Field(0)
type args struct {
context *structContext
}
tests := []struct {
name string
config DefaultConfig
args args
want infra.GoStructorValue
}{
{
name: "get map from default tag not implemented",
config: DefaultConfig{},
args: args{
context: &structContext{
Value: fieldValue,
StructField: fieldType,
},
},
want: infra.NewGoStructorNoValue(fieldValue, errors.New("not implemented")),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig{}
if got := config.GetComplexType(tt.args.context); !reflect.DeepEqual(got, tt.want) {
t.Errorf("DefaultConfig.GetComplexType() = %v, want %v", got, tt.want)
}
})
}
}
47 changes: 20 additions & 27 deletions pipeline/environment_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,37 @@ import (
"fmt"
"os"
"reflect"
"strings"

"github.com/goreflect/gostructor/converters"
"github.com/goreflect/gostructor/infra"
"github.com/goreflect/gostructor/middlewares"
"github.com/goreflect/gostructor/tags"
"github.com/goreflect/gostructor/tools"
)

/*EnvironmentConfig - configuring structures from environment*/
type EnvironmentConfig struct {
}

const (
separator = ","
)

/*
GetComplexType - getting complex types like slices from environment variable
*/
func (config EnvironmentConfig) GetComplexType(context *structContext) infra.GoStructorValue {
valueIndirect := reflect.Indirect(context.Value)
switch valueIndirect.Kind() {
case reflect.Slice:
valueTag := context.StructField.Tag.Get(tags.TagEnvironment)
if valueTag != "" {
value := os.Getenv(valueTag)
// add here additional logic for middlewares and other
array := config.convertStringIntoArray(value)
return converters.ConvertBetweenComplexTypes(reflect.ValueOf(array), valueIndirect)
}
return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("complex type "+valueIndirect.Kind().String()+" not implemented in environment parsing function"))
default:
return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("complex type "+valueIndirect.Kind().String()+" not implemented in environment parsing function"))
valueTag := context.StructField.Tag.Get(tags.TagEnvironment)
if config.checkTagValue(valueTag) {
// TODO: increase message by information about what wrong in future issues
return infra.NewGoStructorNoValue(context.Value, errors.New("can not be empty. "))
}
}

// TODO: Add variant for change separator. Currently it is comma
func (config EnvironmentConfig) convertStringIntoArray(value string) []string {
return strings.Split(value, separator)
value := os.Getenv(valueTag)
if err := middlewares.ExecutorMiddlewaresByTagValue(value, tags.TagEnvironment); err != nil {
return infra.NewGoStructorNoValue(context.Value, errors.New("can not checks by middlewares. err: "+err.Error()))
}
array, err := tools.ConvertStringIntoArray(value, tools.ConfigureConverts{Separator: tools.COMMA})
if err != nil {
return infra.NewGoStructorNoValue(context.Value.Interface(), err)
}
return converters.ConvertBetweenComplexTypes(reflect.ValueOf(array), valueIndirect)
}

/*
Expand All @@ -60,8 +53,8 @@ func (config EnvironmentConfig) GetBaseType(context *structContext) infra.GoStru
return infra.NewGoStructorNoValue(context.Value, errors.New("getBaseType can not get field by empty tag value of tag: "+tags.TagEnvironment))
}

// TODO: using in future for run middlewares
// func (config EnvironmentConfig) checksByMiddlewares(tagvalue string) bool {
// // in the future in this case will be added a call middlewares functions
// return tagvalue == ""
// }
// TODO: change signature by error interface
func (config EnvironmentConfig) checkTagValue(tagvalue string) bool {
// in the future in this case will be added a call middlewares functions
return tagvalue == ""
}
4 changes: 3 additions & 1 deletion pipeline/environment_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func TestEnvironmentConfig_GetBaseType(t *testing.T) {
field1 string `cf_env:"testBaseType"`
}{}
os.Setenv("testBaseType", "tururu")
defer os.Unsetenv("testBaseType")
myStruct1 := reflect.Indirect(reflect.ValueOf(myStruct))
field1 := myStruct1.Type().Field(0)
t.Log("type of field: ", field1.Name+", "+field1.Type.Name())
Expand Down Expand Up @@ -43,7 +44,6 @@ func TestEnvironmentConfig_GetBaseType(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
config := EnvironmentConfig{}
got := config.GetBaseType(tt.args.context)
os.Remove("testBaseType")

if got.Value.String() != tt.want.Value.String() {
t.Errorf("EnvironmentConfig.GetComplexType() = %v, want %v", got, tt.want)
Expand Down Expand Up @@ -96,6 +96,8 @@ func TestEnvironmentConfig_GetComplexType(t *testing.T) {
fieldhard []float32 `cf_env:"mySlice"`
}{}
os.Setenv("mySlice", "1.12,1.24,1.67")
defer os.Unsetenv("mySlice")

myStruct1 := reflect.Indirect(reflect.ValueOf(myStruct))
field1 := myStruct1.Type().Field(0)
t.Log("type of field: ", field1.Name+", "+field1.Type.Name())
Expand Down
5 changes: 2 additions & 3 deletions tags/analys_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ func recurseStructField(structField reflect.StructField) []int {
switch structField.Type.Kind() {
case reflect.Struct:
for i := 0; i < structField.Type.NumField(); i++ {
summarizeLevel := recurseStructField(structField.Type.Field(i))
summarize = combineFields(summarize, summarizeLevel)
summirizeLevel := recurseStructField(structField.Type.Field(i))
summarize = combineFields(summarize, summirizeLevel)
}
}
return summarize
Expand Down Expand Up @@ -72,7 +72,6 @@ func checkFuncsByTags(structField reflect.StructField) []int {
continue
} else {
// TODO: add additional anaylys tag values for middlewares functions and others

summarize[getFuncTypeByTag(value)]++
}
}
Expand Down
36 changes: 36 additions & 0 deletions tools/converts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package tools

import (
"errors"
"strings"
)

type (
// ConfigureConverts - configuration structure for converters tools
ConfigureConverts struct {
Separator SeparatorType
}

// SeparatorType - type for configuring separators
SeparatorType string
)

const (
// COMMA - separator in value is ,
COMMA SeparatorType = ","
)

// ConvertStringIntoArray - converting from string into array of string
func ConvertStringIntoArray(value string, configuration ConfigureConverts) ([]string, error) {
if err := configuration.validation(); err != nil {
return nil, err
}
return strings.Split(value, string(configuration.Separator)), nil
}

func (configure ConfigureConverts) validation() error {
if configure.Separator == "" {
return errors.New("separator can not be empty! ")
}
return nil
}

0 comments on commit ceaad54

Please sign in to comment.