Skip to content

Commit

Permalink
Merge pull request #21 from goreflect/issue_6
Browse files Browse the repository at this point in the history
Issue 6
  • Loading branch information
artemkaxboy committed Apr 5, 2020
2 parents 5485719 + f7339c6 commit 7a73cb8
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 21 deletions.
2 changes: 1 addition & 1 deletion lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func ConfigureSetup(
}

/*
ConfigureSmart - configuring by analys tags for add prefer strategy for configuring
ConfigureSmart - configuring by analysing tags for add prefer strategy for configuring
*/
func ConfigureSmart(
structure interface{},
Expand Down
36 changes: 36 additions & 0 deletions lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gostructor

import (
"fmt"
"os"
"testing"

"github.com/goreflect/gostructor/infra"
Expand Down Expand Up @@ -34,6 +35,14 @@ type (
Field1 string
} `cf_hocon:"node=planC.tururu.tratatat.planZ"`
}

EnvStruct struct {
Field1 int16 `cf_env:"myField1"`
Field2 string `cf_env:"myField2"`
Field3 bool `cf_env:"myField3"`
Field4 float32 `cf_env:"myField4"`
Field5 []bool `cf_env:"myField5"`
}
)

func Test_parseHocon1(t *testing.T) {
Expand Down Expand Up @@ -103,3 +112,30 @@ func Test_smartConfigure(t *testing.T) {
},
}, myStruct.(*MyStruct4))
}

func Test_getValueFromEnvironment(t *testing.T) {
os.Setenv("myField1", "12")
os.Setenv("myField2", "test")
os.Setenv("myField3", "true")
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")
}()
myStruct, err := ConfigureSmart(&EnvStruct{}, "")
if err != nil {
t.Error(err)
}

assert.Equal(t, &EnvStruct{
Field1: 12,
Field2: "test",
Field3: true,
Field4: 12.2,
Field5: []bool{true, false, true},
}, myStruct.(*EnvStruct))
}
52 changes: 48 additions & 4 deletions pipeline/environment_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,65 @@ package pipeline
import (
"errors"
"fmt"
"os"
"reflect"
"strings"

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

/*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 {
fmt.Println("Level: Debug. Message: environment values sources start")
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"))
}
}

return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("getComplexType not implemented for environment configuring"))
// TODO: Add variant for change separator. Currently it is comma
func (config EnvironmentConfig) convertStringIntoArray(value string) []string {
return strings.Split(value, separator)
}

/*
GetBaseType - getting base type values
*/
func (config EnvironmentConfig) GetBaseType(context *structContext) infra.GoStructorValue {
fmt.Println("Level: Debug. Message: environment values sources start")
fmt.Println("Level: Debug. Environment values sources start")
valueIndirect := reflect.Indirect(context.Value)
valueTag := context.StructField.Tag.Get(tags.TagEnvironment)

return infra.NewGoStructorNoValue(context.Value.Interface(), errors.New("getBaseType not implemented for environment configuring"))
if valueTag != "" {
value := os.Getenv(valueTag)
return converters.ConvertBetweenPrimitiveTypes(reflect.ValueOf(value), valueIndirect)
}
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 == ""
// }
132 changes: 132 additions & 0 deletions pipeline/environment_function_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package pipeline

import (
"errors"
"os"
"reflect"
"testing"

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

func TestEnvironmentConfig_GetBaseType(t *testing.T) {
myStruct := struct {
field1 string `cf_env:"testBaseType"`
}{}
os.Setenv("testBaseType", "tururu")
myStruct1 := reflect.Indirect(reflect.ValueOf(myStruct))
field1 := myStruct1.Type().Field(0)
t.Log("type of field: ", field1.Name+", "+field1.Type.Name())
type args struct {
context *structContext
}
tests := []struct {
name string
config EnvironmentConfig
args args
want infra.GoStructorValue
}{
{
name: "get success base type string from environment",
config: EnvironmentConfig{},
args: args{
context: &structContext{
StructField: field1,
Value: myStruct1.Field(0),
},
},
want: infra.NewGoStructorTrueValue(reflect.ValueOf("tururu")),
},
}
for _, tt := range tests {
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)
}
})
}
}

func TestEnvironmentConfig_GetBaseTypeFaield(t *testing.T) {
myStruct := struct {
field1 string `cf_env:""`
}{}
myStruct1 := reflect.Indirect(reflect.ValueOf(myStruct))
field1 := myStruct1.Type().Field(0)
t.Log("type of field: ", field1.Name+", "+field1.Type.Name())
type args struct {
context *structContext
}
tests := []struct {
name string
config EnvironmentConfig
args args
want infra.GoStructorValue
}{
{
name: "get faield base type string from environment because not set name of this value",
config: EnvironmentConfig{},
args: args{
context: &structContext{
StructField: field1,
Value: myStruct1.Field(0),
},
},
want: infra.NewGoStructorNoValue(reflect.ValueOf(myStruct1.Field(0)), errors.New("getBaseType can not get field by empty tag value of tag: "+tags.TagEnvironment)),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := EnvironmentConfig{}
got := config.GetBaseType(tt.args.context)
if got.GetNotAValue().Error.Error() != tt.want.GetNotAValue().Error.Error() {
t.Errorf("EnvironmentConfig.GetComplexType() = %v, want %v", got, tt.want)
}
})
}
}

func TestEnvironmentConfig_GetComplexType(t *testing.T) {
myStruct := struct {
fieldhard []float32 `cf_env:"mySlice"`
}{}
os.Setenv("mySlice", "1.12,1.24,1.67")
myStruct1 := reflect.Indirect(reflect.ValueOf(myStruct))
field1 := myStruct1.Type().Field(0)
t.Log("type of field: ", field1.Name+", "+field1.Type.Name())
type args struct {
context *structContext
}
tests := []struct {
name string
config EnvironmentConfig
args args
want infra.GoStructorValue
}{
{
name: "get slice from environment into float32 slice structure field",
config: EnvironmentConfig{},
args: args{
context: &structContext{
StructField: field1,
Value: myStruct1.Field(0),
},
},
want: infra.NewGoStructorTrueValue(reflect.ValueOf([]float32{1.12, 1.24, 1.67})),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := EnvironmentConfig{}
got := config.GetComplexType(tt.args.context)
if !reflect.DeepEqual(got.Value.Interface(), tt.want.Value.Interface()) {
t.Errorf("EnvironmentConfig.GetComplexType() = %v, want %v", got, tt.want)
}
})
}
}
9 changes: 4 additions & 5 deletions pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const (

notSupportedTypeError = "not supported type "

/*EmptyAdditionalPrefix - prefix for setup before all values can be empty*/
EmptyAdditionalPrefix = ""
)

Expand Down Expand Up @@ -141,7 +140,7 @@ func Configure(
// filename for file configuring
fileName string,
// functions will be configure structure
pipelineChaines []infra.FuncType,
pipelineChains []infra.FuncType,
// prefix by getting data from source placed in entry
prefix string,
// smartConfigure - analys structure by tags for find methods which should use for configuration
Expand All @@ -160,7 +159,7 @@ func Configure(
analysedChains := tags.GetFunctionTypes(structure)
pipeline = getFunctionChain(fileName, analysedChains)
} else {
pipeline = getFunctionChain(fileName, pipelineChaines)
pipeline = getFunctionChain(fileName, pipelineChains)
}

// currentChain := pipeline.chains
Expand Down Expand Up @@ -271,7 +270,7 @@ func (pipeline *Pipeline) configuringValues(context *structContext) error {
return errors.New("can not set " + valueIndirect.Kind().String() + " into struct field.")
}
} else {
return errors.New("Loglevel: Debug Message: value get not implementedable value: ")
return errors.New("Loglevel: Debug Message: value get not implemented value: ")
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return errors.New("not supported types of unsigned integer")
Expand All @@ -286,7 +285,7 @@ func (pipeline *Pipeline) configuringValues(context *structContext) error {
return errors.New("can not set " + valueIndirect.Kind().String() + " into struct field.")
}
} else {
return errors.New("value get not implementedable value: ")
return errors.New("value get not implemented value: ")
}
default:
return errors.New("not supported type for hocon parsing")
Expand Down
23 changes: 12 additions & 11 deletions tags/analys_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import (
)

/*
GetFunctionTypes - return slice of functions which should configuring sourceStruct structure
GetFunctionTypes - return slice of functions which should configure sourceStruct structure
*/
func GetFunctionTypes(sourceStruct interface{}) []infra.FuncType {
summirize := []int{}
summarize := []int{}
value := reflect.Indirect(reflect.ValueOf(sourceStruct))
for i := 0; i < value.NumField(); i++ {
summirizeLevel := recurseStructField(value.Type().Field(i))
summirize = combineFields(summirize, summirizeLevel)
summarize = combineFields(summarize, summirizeLevel)
}
result := []infra.FuncType{}
for funcType, value := range summirize {
for funcType, value := range summarize {
if value > 0 {
result = append(result, infra.FuncType(funcType))
}
Expand All @@ -26,16 +26,16 @@ func GetFunctionTypes(sourceStruct interface{}) []infra.FuncType {
}

func recurseStructField(structField reflect.StructField) []int {
summirize := checkFuncsByTags(structField)
summarize := checkFuncsByTags(structField)

switch structField.Type.Kind() {
case reflect.Struct:
for i := 0; i < structField.Type.NumField(); i++ {
summirizeLevel := recurseStructField(structField.Type.Field(i))
summirize = combineFields(summirize, summirizeLevel)
summarizeLevel := recurseStructField(structField.Type.Field(i))
summarize = combineFields(summarize, summarizeLevel)
}
}
return summirize
return summarize
}

//TODO: decomposition
Expand All @@ -57,7 +57,7 @@ func combineFields(summCurrent []int, newSumm []int) []int {
}

func checkFuncsByTags(structField reflect.StructField) []int {
summirize := make([]int, AmountTags) // amount repeats tags
summarize := make([]int, AmountTags) // amount repeats tags
for _, value := range []string{
TagYaml,
TagJson,
Expand All @@ -72,11 +72,12 @@ func checkFuncsByTags(structField reflect.StructField) []int {
continue
} else {
// TODO: add additional anaylys tag values for middlewares functions and others
summirize[getFuncTypeByTag(value)]++

summarize[getFuncTypeByTag(value)]++
}
}

return summirize
return summarize
}

func getFuncTypeByTag(tagName string) infra.FuncType {
Expand Down

0 comments on commit 7a73cb8

Please sign in to comment.