-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
isolated test fixtures
- Loading branch information
Showing
18 changed files
with
1,625 additions
and
323 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: CI workflow | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
jobs: | ||
|
||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: 1.18.1 | ||
|
||
- name: Test | ||
run: go test -v ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
.DS_Store | ||
cmd/eval-server/server | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
GOLANGCI_LINT_VERSION=v1.37.1 | ||
|
||
ifndef GOPATH | ||
GOPATH := $(shell go env GOPATH) | ||
endif | ||
|
||
# Default target will fetch deps, build and run tests. | ||
all: tidy generate build check test | ||
|
||
generate: | ||
oapi-codegen -generate types -package=validator client-v1.yaml > types.gen.go | ||
|
||
tidy: | ||
go mod tidy | ||
|
||
build: | ||
go build ./... | ||
|
||
check: format lint sec | ||
|
||
clean: | ||
go clean | ||
|
||
# Format go code and error if any changes are made | ||
PHONY+= format | ||
format: | ||
@echo "Checking that go fmt does not make any changes..." | ||
@test -z $$(go fmt $(go list ./...)) || (echo "go fmt would make a change. Please verify and commit the proposed changes"; exit 1) | ||
@echo "Checking go fmt complete" | ||
@echo "Running goimports" | ||
@test -z $$(goimports -w ./..) || (echo "goimports would make a change. Please verify and commit the proposed changes"; exit 1) | ||
|
||
PHONY+= lint | ||
lint: $(GOPATH)/bin/golangci-lint $(GOPATH)/bin/golint | ||
@echo "Linting $(1)" | ||
@golint -set_exit_status ./... | ||
@go vet ./... | ||
@golangci-lint run \ | ||
-E asciicheck \ | ||
-E bodyclose \ | ||
-E exhaustive \ | ||
-E exportloopref \ | ||
-E gofmt \ | ||
-E goimports \ | ||
-E gosec \ | ||
-E noctx \ | ||
-E nolintlint \ | ||
-E rowserrcheck \ | ||
-E exportloopref \ | ||
-E sqlclosecheck \ | ||
-E stylecheck \ | ||
-E unconvert \ | ||
-E unparam | ||
@echo "Lint-free" | ||
|
||
# | ||
# Install Tools | ||
# | ||
PHONY+= sec | ||
sec: $(GOPATH)/bin/gosec | ||
@echo "Checking for security problems ..." | ||
@gosec -quiet -confidence high -severity medium ./... | ||
@echo "No problems found"; \ | ||
|
||
$(GOPATH)/bin/golangci-lint: | ||
@echo "🔘 Installing golangci-lint... (`date '+%H:%M:%S'`)" | ||
@curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin | ||
|
||
$(GOPATH)/bin/golint: | ||
@echo "🔘 Installing golint ... (`date '+%H:%M:%S'`)" | ||
@GO111MODULE=off go get -u golang.org/x/lint/golint | ||
|
||
$(GOPATH)/bin/goimports: | ||
@echo "🔘 Installing goimports ... (`date '+%H:%M:%S'`)" | ||
@GO111MODULE=off go get -u golang.org/x/tools/cmd/goimports | ||
|
||
$(GOPATH)/bin/gosec: | ||
@echo "🔘 Installing gosec ... (`date '+%H:%M:%S'`)" | ||
@curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(GOPATH)/bin | ||
|
||
|
||
$(GOPATH)/bin/oapi-codegen: | ||
@echo "🔘 Installing oapicodegen ... (`date '+%H:%M:%S'`)" | ||
@go get github.com/deepmap/oapi-codegen/cmd/[email protected] | ||
|
||
PHONY+= tools | ||
tools: $(GOPATH)/bin/golangci-lint $(GOPATH)/bin/golint $(GOPATH)/bin/gosec $(GOPATH)/bin/goimports $(GOPATH)/bin/oapi-codegen | ||
|
||
PHONY+= update-tools | ||
update-tools: delete-tools $(GOPATH)/bin/golangci-lint $(GOPATH)/bin/golint $(GOPATH)/bin/gosec $(GOPATH)/bin/goimports | ||
|
||
PHONY+= delete-tools | ||
delete-tools: | ||
@rm $(GOPATH)/bin/golangci-lint | ||
@rm $(GOPATH)/bin/gosec | ||
@rm $(GOPATH)/bin/golint | ||
@rm $(GOPATH)/bin/goimports | ||
|
||
|
||
.PHONY: all tidy generate build clean test lint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,135 @@ | ||
# Server SDK - Evaluator test cases | ||
|
||
|
||
## Example | ||
Evaluator integration test in golang. This test model can be implemented in any programming language. | ||
```go | ||
package tests | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"path/filepath" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/harness/ff-golang-server-sdk/evaluation" | ||
|
||
"github.com/harness/ff-golang-server-sdk/log" | ||
"github.com/harness/ff-golang-server-sdk/pkg/repository" | ||
"github.com/harness/ff-golang-server-sdk/rest" | ||
) | ||
|
||
const source = "./ff-test-cases/tests" | ||
|
||
type test struct { | ||
Flag string `json:"flag"` | ||
Target *string `json:"target"` | ||
Expected interface{} `json:"expected"` | ||
} | ||
|
||
type testFile struct { | ||
Filename string | ||
Flags []rest.FeatureConfig `json:"flags"` | ||
Segments []rest.Segment `json:"segments"` | ||
Targets []evaluation.Target `json:"targets"` | ||
Tests []test `json:"tests"` | ||
} | ||
|
||
func loadFiles() []testFile { | ||
files, err := ioutil.ReadDir(source) | ||
if err != nil { | ||
log.Error(err) | ||
} | ||
|
||
slice := make([]testFile, 0, len(files)) | ||
for _, file := range files { | ||
if file.IsDir() || filepath.Ext(file.Name()) != ".json" { | ||
continue | ||
} | ||
if f, err := loadFile(file.Name()); err == nil { | ||
slice = append(slice, f) | ||
} | ||
} | ||
return slice | ||
} | ||
|
||
func loadFile(filename string) (testFile, error) { | ||
fp := filepath.Clean(filepath.Join(source, filename)) | ||
content, err := ioutil.ReadFile(fp) | ||
if err != nil { | ||
log.Error(err) | ||
return testFile{}, err | ||
} | ||
|
||
result := testFile{ | ||
Filename: filename, | ||
} | ||
err = json.Unmarshal(content, &result) | ||
if err != nil { | ||
log.Error(err) | ||
return testFile{}, err | ||
} | ||
return result, nil | ||
} | ||
|
||
func TestEvaluator(t *testing.T) { | ||
t.Parallel() | ||
fixtures := loadFiles() | ||
for _, fixture := range fixtures { | ||
lruCache, err := repository.NewLruCache(1000) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
repo := repository.New(lruCache) | ||
evaluator, err := evaluation.NewEvaluator(repo, nil) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
for _, flag := range fixture.Flags { | ||
repo.SetFlag(flag) | ||
} | ||
for _, segment := range fixture.Segments { | ||
repo.SetSegment(segment) | ||
} | ||
|
||
for _, testCase := range fixture.Tests { | ||
testName := fmt.Sprintf("test fixture %s with flag %s", fixture.Filename, testCase.Flag) | ||
if testCase.Target != nil { | ||
testName = fmt.Sprintf("%s and target %s", testName, *testCase.Target) | ||
} | ||
t.Run(testName, func(t *testing.T) { | ||
var target *evaluation.Target | ||
if testCase.Target != nil { | ||
for i, val := range fixture.Targets { | ||
if val.Identifier == *testCase.Target { | ||
target = &fixture.Targets[i] | ||
} | ||
} | ||
} | ||
var got interface{} | ||
flag, err := repo.GetFlag(testCase.Flag) | ||
if err != nil { | ||
t.Errorf("flag %s not found", testCase.Flag) | ||
} | ||
switch flag.Kind { | ||
case "boolean": | ||
got = evaluator.BoolVariation(testCase.Flag, target, false) | ||
case "string": | ||
got = evaluator.StringVariation(testCase.Flag, target, "blue") | ||
case "int": | ||
got = evaluator.IntVariation(testCase.Flag, target, 100) | ||
case "number": | ||
got = evaluator.NumberVariation(testCase.Flag, target, 50.00) | ||
case "json": | ||
got = evaluator.JSONVariation(testCase.Flag, target, map[string]interface{}{}) | ||
} | ||
if !reflect.DeepEqual(got, testCase.Expected) { | ||
t.Errorf("eval engine got = %v, want %v", got, testCase.Expected) | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
``` |
Oops, something went wrong.