diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c0f65a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +lib/coverage.out +coverage.out diff --git a/Makefile b/Makefile index d513e94..b148824 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ lint: - golint lib && golint lib/internal/models && golint lib/internal/utils && golint lib/internal/messages && golint lib/internal/constants && golint examples + golint lib && golint lib/models && golint lib/internal/utils && golint lib/internal/messages && golint lib/internal/constants && golint examples testLib: cd lib/ && go test -coverprofile=coverage.out testLibModels: - cd lib/internal/models && go test -coverprofile=coverage.out + cd lib/models && go test -coverprofile=coverage.out testLibUtils: cd lib/internal/utils && go test -coverprofile=coverage.out diff --git a/go.mod b/go.mod index d993644..ee80077 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/robfig/cron v1.2.0 github.com/sirupsen/logrus v1.7.0 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect golang.org/x/text v0.3.6 // indirect diff --git a/go.sum b/go.sum index b4ff9fa..69691cb 100644 --- a/go.sum +++ b/go.sum @@ -128,12 +128,14 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= diff --git a/lib/AppConfiguration.go b/lib/AppConfiguration.go index 8d1190d..7daa8b3 100644 --- a/lib/AppConfiguration.go +++ b/lib/AppConfiguration.go @@ -21,10 +21,17 @@ import ( "os" "github.com/IBM/appconfiguration-go-sdk/lib/internal/messages" - "github.com/IBM/appconfiguration-go-sdk/lib/internal/models" "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils/log" + "github.com/IBM/appconfiguration-go-sdk/lib/models" ) +// AppConfigurationInterface contains methods used to interact with certain app configuration services +// IMPORTANT: Any change in this interface requires re-generation of mocks using command "$GOPATH/bin/mockery -name AppConfigurationInterface" +type AppConfigurationInterface interface { + GetFeature(featureID string) (models.Feature, error) + GetFeatures() (map[string]models.Feature, error) +} + // AppConfiguration : Struct having init and configInstance. type AppConfiguration struct { isInitialized bool diff --git a/lib/ConfigurationHandler.go b/lib/ConfigurationHandler.go index 57eb221..37418ea 100644 --- a/lib/ConfigurationHandler.go +++ b/lib/ConfigurationHandler.go @@ -20,17 +20,18 @@ import ( "bytes" "encoding/json" "errors" + "net/http" + "path" + "sync" + "time" + "github.com/IBM/appconfiguration-go-sdk/lib/internal/constants" "github.com/IBM/appconfiguration-go-sdk/lib/internal/messages" - "github.com/IBM/appconfiguration-go-sdk/lib/internal/models" "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils" "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils/log" + "github.com/IBM/appconfiguration-go-sdk/lib/models" "github.com/IBM/go-sdk-core/v5/core" "github.com/gorilla/websocket" - "net/http" - "path" - "sync" - "time" ) type configurationUpdateListenerFunc func() diff --git a/lib/appconfiguration_test.go b/lib/appconfiguration_test.go index c8fe231..b21ca4a 100644 --- a/lib/appconfiguration_test.go +++ b/lib/appconfiguration_test.go @@ -19,7 +19,7 @@ package lib import ( "testing" - "github.com/IBM/appconfiguration-go-sdk/lib/internal/models" + "github.com/IBM/appconfiguration-go-sdk/lib/models" // "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils/log" "github.com/stretchr/testify/assert" @@ -87,14 +87,13 @@ func TestSetContext(t *testing.T) { ac.isInitialized = true ac.SetContext("c1", "dev", ContextOptions{ BootstrapFile: "saflights/flights.json", - LiveConfigUpdateEnabled: &F, + LiveConfigUpdateEnabled: F, }, ContextOptions{ BootstrapFile: "saflights/flights.json", - LiveConfigUpdateEnabled: &F, + LiveConfigUpdateEnabled: F, }) - if hook.LastEntry().Message != "AppConfiguration - Incorrect usage of context options. At most of one ContextOptions struct should be passed." { - t.Errorf("Test failed: Incorrect error message") - } + + assert.Equal(t, hook.LastEntry().Message, "AppConfiguration - Incorrect usage of context options. At most of one ContextOptions struct should be passed.") reset(ac) // when collection id and environment id is provided successfully and the number of context options is 1. (Bootstrap file evaluation) @@ -103,7 +102,7 @@ func TestSetContext(t *testing.T) { assert.Equal(t, false, ac.isInitializedConfig) ac.SetContext("c1", "dev", ContextOptions{ BootstrapFile: "saflights/flights.json", - LiveConfigUpdateEnabled: &F, + LiveConfigUpdateEnabled: F, }) assert.Equal(t, true, ac.isInitializedConfig) reset(ac) @@ -113,12 +112,10 @@ func TestSetContext(t *testing.T) { ac.isInitialized = true assert.Equal(t, false, ac.isInitializedConfig) ac.SetContext("c1", "dev", ContextOptions{ - BootstrapFile: "", - LiveConfigUpdateEnabled: &F, + ConfigurationFile: "", + LiveConfigUpdateEnabled: F, }) - if hook.LastEntry().Message != "AppConfiguration - Provide configuration_file value when live_config_update_enabled is false." { - t.Errorf("Test failed: Incorrect error message") - } + assert.Equal(t, hook.LastEntry().Message, "AppConfiguration - Provide bootstrap_file value when live_config_update_enabled is false.") reset(ac) } func TestGetFeature(t *testing.T) { diff --git a/lib/configurationhandler_test.go b/lib/configurationhandler_test.go index af1118e..53d7349 100644 --- a/lib/configurationhandler_test.go +++ b/lib/configurationhandler_test.go @@ -25,9 +25,9 @@ import ( "testing" "time" - "github.com/IBM/appconfiguration-go-sdk/lib/internal/models" "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils" "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils/log" + "github.com/IBM/appconfiguration-go-sdk/lib/models" "github.com/IBM/go-sdk-core/v5/core" "github.com/gorilla/websocket" "github.com/sirupsen/logrus/hooks/test" @@ -54,7 +54,7 @@ func TestConfigHandlerSetContext(t *testing.T) { ch := GetConfigurationHandlerInstance() ch.SetContext("c1", "dev", ContextOptions{ BootstrapFile: "flights.json", - LiveConfigUpdateEnabled: &F, + LiveConfigUpdateEnabled: F, }) assert.Equal(t, "c1", ch.collectionID) assert.Equal(t, "dev", ch.environmentID) diff --git a/lib/mocks/AppConfigurationInterface.go b/lib/mocks/AppConfigurationInterface.go new file mode 100644 index 0000000..2550a45 --- /dev/null +++ b/lib/mocks/AppConfigurationInterface.go @@ -0,0 +1,57 @@ +// Code generated by mockery v2.0.0-alpha.2. DO NOT EDIT. + +package mocks + +import ( + models "github.com/IBM/appconfiguration-go-sdk/lib/models" + mock "github.com/stretchr/testify/mock" +) + +// AppConfigurationInterface is an autogenerated mock type for the AppConfigurationInterface type +type AppConfigurationInterface struct { + mock.Mock +} + +// GetFeature provides a mock function with given fields: featureID +func (_m *AppConfigurationInterface) GetFeature(featureID string) (models.Feature, error) { + ret := _m.Called(featureID) + + var r0 models.Feature + if rf, ok := ret.Get(0).(func(string) models.Feature); ok { + r0 = rf(featureID) + } else { + r0 = ret.Get(0).(models.Feature) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(featureID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetFeatures provides a mock function with given fields: +func (_m *AppConfigurationInterface) GetFeatures() (map[string]models.Feature, error) { + ret := _m.Called() + + var r0 map[string]models.Feature + if rf, ok := ret.Get(0).(func() map[string]models.Feature); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]models.Feature) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/lib/internal/models/Cache.go b/lib/models/Cache.go similarity index 100% rename from lib/internal/models/Cache.go rename to lib/models/Cache.go diff --git a/lib/internal/models/Collection.go b/lib/models/Collection.go similarity index 100% rename from lib/internal/models/Collection.go rename to lib/models/Collection.go diff --git a/lib/internal/models/ConfigResponse.go b/lib/models/ConfigResponse.go similarity index 100% rename from lib/internal/models/ConfigResponse.go rename to lib/models/ConfigResponse.go diff --git a/lib/internal/models/ConfigurationType.go b/lib/models/ConfigurationType.go similarity index 100% rename from lib/internal/models/ConfigurationType.go rename to lib/models/ConfigurationType.go diff --git a/lib/internal/models/Feature.go b/lib/models/Feature.go similarity index 88% rename from lib/internal/models/Feature.go rename to lib/models/Feature.go index cedee8a..bd13819 100644 --- a/lib/internal/models/Feature.go +++ b/lib/models/Feature.go @@ -26,6 +26,20 @@ import ( "github.com/IBM/appconfiguration-go-sdk/lib/internal/utils/log" ) +// FeatureInterface contains methods used to interact with certain app configuration feature services +// IMPORTANT: Any change in this interface requires re-generation of mocks using command "$GOPATH/bin/mockery -name FeatureInterface" +type FeatureInterface interface { + GetFeatureName() string + GetDisabledValue() interface{} + GetEnabledValue() interface{} + GetFeatureID() string + GetFeatureDataType() string + GetFeatureDataFormat() string + IsEnabled() bool + GetSegmentRules() []SegmentRule + GetCurrentValue(entityID string, entityAttributes map[string]interface{}) interface{} +} + // Feature : Feature struct type Feature struct { Name string `json:"name"` @@ -38,6 +52,11 @@ type Feature struct { Enabled bool `json:"enabled"` } +// NewFeature : New object used for mocking +func NewFeature() FeatureInterface { + return &Feature{} +} + // GetFeatureName : Get Feature Name func (f *Feature) GetFeatureName() string { return f.Name diff --git a/lib/internal/models/Property.go b/lib/models/Property.go similarity index 100% rename from lib/internal/models/Property.go rename to lib/models/Property.go diff --git a/lib/internal/models/Rule.go b/lib/models/Rule.go similarity index 100% rename from lib/internal/models/Rule.go rename to lib/models/Rule.go diff --git a/lib/internal/models/Segment.go b/lib/models/Segment.go similarity index 100% rename from lib/internal/models/Segment.go rename to lib/models/Segment.go diff --git a/lib/internal/models/SegmentRule.go b/lib/models/SegmentRule.go similarity index 100% rename from lib/internal/models/SegmentRule.go rename to lib/models/SegmentRule.go diff --git a/lib/models/mocks/FeatureInterface.go b/lib/models/mocks/FeatureInterface.go new file mode 100644 index 0000000..9b349bc --- /dev/null +++ b/lib/models/mocks/FeatureInterface.go @@ -0,0 +1,147 @@ +// Code generated by mockery v2.0.0-alpha.2. DO NOT EDIT. + +package mocks + +import ( + models "github.com/IBM/appconfiguration-go-sdk/lib/models" + mock "github.com/stretchr/testify/mock" +) + +// FeatureInterface is an autogenerated mock type for the FeatureInterface type +type FeatureInterface struct { + mock.Mock +} + +// GetCurrentValue provides a mock function with given fields: entityID, entityAttributes +func (_m *FeatureInterface) GetCurrentValue(entityID string, entityAttributes map[string]interface{}) interface{} { + ret := _m.Called(entityID, entityAttributes) + + var r0 interface{} + if rf, ok := ret.Get(0).(func(string, map[string]interface{}) interface{}); ok { + r0 = rf(entityID, entityAttributes) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } + } + + return r0 +} + +// GetDisabledValue provides a mock function with given fields: +func (_m *FeatureInterface) GetDisabledValue() interface{} { + ret := _m.Called() + + var r0 interface{} + if rf, ok := ret.Get(0).(func() interface{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } + } + + return r0 +} + +// GetEnabledValue provides a mock function with given fields: +func (_m *FeatureInterface) GetEnabledValue() interface{} { + ret := _m.Called() + + var r0 interface{} + if rf, ok := ret.Get(0).(func() interface{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } + } + + return r0 +} + +// GetFeatureDataFormat provides a mock function with given fields: +func (_m *FeatureInterface) GetFeatureDataFormat() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetFeatureDataType provides a mock function with given fields: +func (_m *FeatureInterface) GetFeatureDataType() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetFeatureID provides a mock function with given fields: +func (_m *FeatureInterface) GetFeatureID() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetFeatureName provides a mock function with given fields: +func (_m *FeatureInterface) GetFeatureName() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetSegmentRules provides a mock function with given fields: +func (_m *FeatureInterface) GetSegmentRules() []models.SegmentRule { + ret := _m.Called() + + var r0 []models.SegmentRule + if rf, ok := ret.Get(0).(func() []models.SegmentRule); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]models.SegmentRule) + } + } + + return r0 +} + +// IsEnabled provides a mock function with given fields: +func (_m *FeatureInterface) IsEnabled() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} diff --git a/lib/internal/models/models_test.go b/lib/models/models_test.go similarity index 100% rename from lib/internal/models/models_test.go rename to lib/models/models_test.go