From 672bb79d6abd76e14fbf70767fce9a92d9b3ec63 Mon Sep 17 00:00:00 2001 From: Marcus Ortense Date: Mon, 1 Apr 2024 19:56:19 -0300 Subject: [PATCH 1/3] feat: add internal structures --- Makefile | 2 +- README.md | 6 +++ go.mod | 8 ++++ go.sum | 10 +++++ internal/client/client.go | 11 +++++ internal/repository/memory_repo/tag.go | 31 ++++++++++++++ internal/tag/tag.go | 15 +++++++ internal/usecase/get_tag_status.go | 34 +++++++++++++++ internal/usecase/get_tag_status_test.go | 57 +++++++++++++++++++++++++ 9 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 go.sum create mode 100644 internal/client/client.go create mode 100644 internal/repository/memory_repo/tag.go create mode 100644 internal/tag/tag.go create mode 100644 internal/usecase/get_tag_status.go create mode 100644 internal/usecase/get_tag_status_test.go diff --git a/Makefile b/Makefile index e2cf4bb..2a700c1 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ build: go build -o ./bin/app ./cmd/main.go test: - go test ./... + go test -v ./... run: go run ./cmd/main.go diff --git a/README.md b/README.md index eed9361..3830185 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # feature-tag How manage feature tags with go? + + +## Use case + +- Retorna todas as tags ativas. +- Verifica se {tag} está ativa? diff --git a/go.mod b/go.mod index c8e7690..5d6d8f8 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module github.com/mist-gopher/feature-tag go 1.22.0 + +require github.com/stretchr/testify v1.9.0 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..60ce688 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/client/client.go b/internal/client/client.go new file mode 100644 index 0000000..b8a4241 --- /dev/null +++ b/internal/client/client.go @@ -0,0 +1,11 @@ +package client + +type Client struct { + Id string + Keys []ClientKey +} + +type ClientKey struct { + Name string + Value string +} diff --git a/internal/repository/memory_repo/tag.go b/internal/repository/memory_repo/tag.go new file mode 100644 index 0000000..641bdd3 --- /dev/null +++ b/internal/repository/memory_repo/tag.go @@ -0,0 +1,31 @@ +package memory_repo + +import ( + "github.com/mist-gopher/feature-tag/internal/tag" +) + +type Tag struct { + Data map[string]tag.Tag + Err error +} + +func NewTagRepositoryInMemory() Tag { + return Tag{ + Data: map[string]tag.Tag{}, + Err: nil, + } +} + +func (repo *Tag) GetByName(name string) (*tag.Tag, error) { + value, exist := repo.Data[name] + + if repo.Err != nil { + return nil, repo.Err + } + + if exist { + return &value, nil + } + + return nil, nil +} diff --git a/internal/tag/tag.go b/internal/tag/tag.go new file mode 100644 index 0000000..918b5cd --- /dev/null +++ b/internal/tag/tag.go @@ -0,0 +1,15 @@ +package tag + +type Tag struct { + Id string + Name string + Value bool +} + +func New(clientId, name string, value bool) Tag { + return Tag{ + Id: "tag:" + clientId + ":" + name, + Name: name, + Value: value, + } +} diff --git a/internal/usecase/get_tag_status.go b/internal/usecase/get_tag_status.go new file mode 100644 index 0000000..0cd2220 --- /dev/null +++ b/internal/usecase/get_tag_status.go @@ -0,0 +1,34 @@ +package usecase + +import ( + "github.com/mist-gopher/feature-tag/internal/tag" +) + +type GetTagStatusInput struct { + AppId string + ApiKey string + TagName string +} + +type GetTagStatusOutput struct { + Active bool +} + +type GetTagByNameRepository interface { + GetByName(name string) (*tag.Tag, error) +} + +func GetTagStatus(input GetTagStatusInput, repo GetTagByNameRepository) (GetTagStatusOutput, error) { + output := GetTagStatusOutput{Active: false} + tag, err := repo.GetByName(tag.New(input.AppId, input.TagName, false).Id) + + if err != nil { + return output, err + } + + if tag != nil { + output.Active = tag.Value + } + + return output, nil +} diff --git a/internal/usecase/get_tag_status_test.go b/internal/usecase/get_tag_status_test.go new file mode 100644 index 0000000..b895cd1 --- /dev/null +++ b/internal/usecase/get_tag_status_test.go @@ -0,0 +1,57 @@ +package usecase_test + +import ( + "testing" + + "github.com/mist-gopher/feature-tag/internal/repository/memory_repo" + "github.com/mist-gopher/feature-tag/internal/tag" + "github.com/mist-gopher/feature-tag/internal/usecase" + "github.com/stretchr/testify/assert" +) + +func MockTagData() map[string]tag.Tag { + activeTag := tag.New("valid key", "tagname", true) + return map[string]tag.Tag{ + activeTag.Id: activeTag, + } +} + +func TestGetTagStatus(t *testing.T) { + type TestCase struct { + input usecase.GetTagStatusInput + resultValue bool + resultError error + } + + cases := map[string]TestCase{ + "with valid input for active tag": { + input: usecase.GetTagStatusInput{ + AppId: "valid key", + ApiKey: "valid id", + TagName: "tagname", + }, + resultValue: true, + resultError: nil, + }, + "unknown tag": { + input: usecase.GetTagStatusInput{ + AppId: "valid key", + ApiKey: "valid id", + TagName: "not a created tag", + }, + resultValue: false, + resultError: nil, + }, + } + + repo := memory_repo.NewTagRepositoryInMemory() + repo.Data = MockTagData() + + for testName, testCase := range cases { + t.Run(testName, func(t *testing.T) { + result, err := usecase.GetTagStatus(testCase.input, &repo) + assert.Equal(t, nil, err) + assert.Equal(t, testCase.resultValue, result.Active) + }) + } +} From be1d238cd9aee50d355323a51554403ab4c4a9d9 Mon Sep 17 00:00:00 2001 From: Marcus Ortense Date: Tue, 2 Apr 2024 18:45:09 -0300 Subject: [PATCH 2/3] chore: code review suggestion --- internal/repository/memory_repo/tag.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/repository/memory_repo/tag.go b/internal/repository/memory_repo/tag.go index 641bdd3..b3470b9 100644 --- a/internal/repository/memory_repo/tag.go +++ b/internal/repository/memory_repo/tag.go @@ -17,15 +17,15 @@ func NewTagRepositoryInMemory() Tag { } func (repo *Tag) GetByName(name string) (*tag.Tag, error) { - value, exist := repo.Data[name] - if repo.Err != nil { return nil, repo.Err } - if exist { - return &value, nil + value, exist := repo.Data[name] + + if !exist { + return nil, nil } - return nil, nil + return &value, nil } From 10842cca5eef07535a81a6e1470385cef52a03ed Mon Sep 17 00:00:00 2001 From: Marcus Ortense Date: Tue, 2 Apr 2024 22:51:46 -0300 Subject: [PATCH 3/3] test: improve tag test --- internal/tag/tag.go | 9 +++++++-- internal/tag/tag_test.go | 16 ++++++++++++++++ internal/usecase/get_tag_status.go | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 internal/tag/tag_test.go diff --git a/internal/tag/tag.go b/internal/tag/tag.go index 918b5cd..d4e8ce8 100644 --- a/internal/tag/tag.go +++ b/internal/tag/tag.go @@ -8,8 +8,13 @@ type Tag struct { func New(clientId, name string, value bool) Tag { return Tag{ - Id: "tag:" + clientId + ":" + name, - Name: name, + Id: MakeId(name, clientId), + Name: name, Value: value, } } + +func MakeId(name, clientId string) string { + return "tag:" + clientId + ":" + name +} + diff --git a/internal/tag/tag_test.go b/internal/tag/tag_test.go new file mode 100644 index 0000000..a13c4c1 --- /dev/null +++ b/internal/tag/tag_test.go @@ -0,0 +1,16 @@ +package tag_test + +import ( + "testing" + + "github.com/mist-gopher/feature-tag/internal/tag" + "github.com/stretchr/testify/assert" +) + +func TestNewTag(t *testing.T){ + ntag := tag.New("clientid", "tagname", false) + assert.Equal(t, "tag:clientid:tagname", ntag.Id) + assert.Equal(t, "tagname", ntag.Name) + assert.False(t, ntag.Value) +} + diff --git a/internal/usecase/get_tag_status.go b/internal/usecase/get_tag_status.go index 0cd2220..b1d3719 100644 --- a/internal/usecase/get_tag_status.go +++ b/internal/usecase/get_tag_status.go @@ -20,7 +20,7 @@ type GetTagByNameRepository interface { func GetTagStatus(input GetTagStatusInput, repo GetTagByNameRepository) (GetTagStatusOutput, error) { output := GetTagStatusOutput{Active: false} - tag, err := repo.GetByName(tag.New(input.AppId, input.TagName, false).Id) + tag, err := repo.GetByName(tag.MakeId(input.TagName, input.AppId)) if err != nil { return output, err