Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: in-memory provider for sdk testing #192

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- name: Run flagd-testbed
run: docker run -d -p 8013:8013 -v ${{ github.workspace }}/test-harness/testing-flags.json:/testing-flags.json ghcr.io/open-feature/flagd-testbed:v0.2.2
- name: Setup Environment
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
Expand Down
27 changes: 13 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,36 @@ Run unit tests with `make test`.

#### End-to-End tests

The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features) using the [flagd provider](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/flagd), [flagd](https://github.com/open-feature/flagd) and [the flagd test module](https://github.com/open-feature/go-sdk-contrib/tree/main/tests/flagd).
The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features).

If you'd like to run them locally, first pull the `test-harness` git submodule

```
git submodule update --init --recursive
```
then start the flagd testbed with
```
docker run -p 8013:8013 -v $PWD/test-harness/testing-flags.json:/testing-flags.json ghcr.io/open-feature/flagd-testbed:latest
```
and finally run

and run tests with,
```
make e2e-test
```

#### Fuzzing

[Go supports fuzzing natively as of 1.18](https://go.dev/security/fuzz/).
The fuzzing suite is implemented as an integration of `go-sdk` with the [flagd provider](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/flagd) and [flagd](https://github.com/open-feature/flagd).
The fuzzing tests are found in [./integration/evaluation_fuzz_test.go](./integration/evaluation_fuzz_test.go), they are dependent on the flagd testbed running, you can start it with
```
docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest
```
then, to execute a fuzzing test, run the following
The fuzzing suite is implemented as an integration of `go-sdk`.
The fuzzing tests are found in [./integration/evaluation_fuzz_test.go](./e2e/evaluation_fuzz_test.go).


To execute a fuzzing test, run the following
```
go test -fuzz=FuzzBooleanEvaluation ./integration/evaluation_fuzz_test.go
go test -fuzz=FuzzBooleanEvaluation ./e2e/evaluation_fuzz_test.go
```
substituting the name of the fuzz as appropriate.

### Releases

This repo uses Release Please to release packages. Release Please sets up a running PR that tracks all changes for the library components, and maintains the versions according to conventional commits, generated when PRs are merged. When Release Please's running PR is merged, any changed artifacts are published.
This repo uses Release Please to release packages. Release Please set up a running PR that tracks all changes for the library components, and maintains the versions according to conventional commits, generated when PRs are merged.
When Release Please PR is merged, any changed artifacts will be published.

## Contacting us

Expand Down
6 changes: 2 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ mockgen:
mockgen -source=pkg/openfeature/hooks.go -destination=pkg/openfeature/hooks_mock_test.go -package=openfeature
test:
go test --short -cover ./...
e2e-test: # dependent on: docker run -p 8013:8013 -v $PWD/test-harness/testing-flags.json:/testing-flags.json ghcr.io/open-feature/flagd-testbed:latest
go test -cover ./...
cd test-harness; git restore testing-flags.json; cd .. # reset testing-flags.json

e2e-test:
go test -race -cover ./e2e/...
lint:
go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
${GOPATH}/bin/golangci-lint run --deadline=3m --timeout=3m ./... # Run linters
5 changes: 5 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## end-to-end tests

This folder contains e2e tests for go-sdk. Tests written here rely on `InMemoryProvider` to perform flag evaluations.
Some tests require `test-harness` Git submodule and use behaviour driven tests defined with [Gherkin](https://cucumber.io/docs/gherkin/reference/) syntax.

36 changes: 0 additions & 36 deletions e2e/caching_test.go

This file was deleted.

112 changes: 112 additions & 0 deletions e2e/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package e2e_test

import (
"github.com/open-feature/go-sdk/pkg/openfeature"
"github.com/open-feature/go-sdk/pkg/openfeature/memprovider"
)

// ctxFunction is a context based evaluation callback
var ctxFunction = func(this memprovider.InMemoryFlag, evalCtx openfeature.FlattenedContext) (
interface{}, openfeature.ProviderResolutionDetail) {

defaultValue := this.Variants[this.DefaultVariant]
defaultResolution := openfeature.ProviderResolutionDetail{
Reason: openfeature.DefaultReason,
Variant: this.DefaultVariant,
}

expects := openfeature.FlattenedContext{
"fn": "Sulisław",
"ln": "Świętopełk",
"age": int64(29),
"customer": false,
}

for k, v := range expects {
if v != evalCtx[k] {
return defaultValue, defaultResolution
}
}

return this.Variants["internal"], openfeature.ProviderResolutionDetail{
Reason: openfeature.TargetingMatchReason,
Variant: "internal",
}
}

var memoryFlags = map[string]memprovider.InMemoryFlag{
"boolean-flag": {
Key: "boolean-flag",
State: memprovider.Enabled,
DefaultVariant: "on",
Variants: map[string]interface{}{
"on": true,
"off": false,
},
ContextEvaluator: nil,
},
"string-flag": {
Key: "string-flag",
State: memprovider.Enabled,
DefaultVariant: "greeting",
Variants: map[string]interface{}{
"greeting": "hi",
"parting": "bye",
},
ContextEvaluator: nil,
},
"integer-flag": {
Key: "integer-flag",
State: memprovider.Enabled,
DefaultVariant: "ten",
Variants: map[string]interface{}{
"one": 1,
"ten": 10,
},
ContextEvaluator: nil,
},
"float-flag": {
Key: "float-flag",
State: memprovider.Enabled,
DefaultVariant: "half",
Variants: map[string]interface{}{
"tenth": 0.1,
"half": 0.5,
},
ContextEvaluator: nil,
},
"object-flag": {
Key: "object-flag",
State: memprovider.Enabled,
DefaultVariant: "template",
Variants: map[string]interface{}{
"empty": map[string]interface{}{},
"template": map[string]interface{}{
"showImages": true,
"title": "Check out these pics!",
"imagesPerPage": 100,
},
},
ContextEvaluator: nil,
},
"wrong-flag": {
Key: "wrong-flag",
State: memprovider.Enabled,
DefaultVariant: "one",
Variants: map[string]interface{}{
"one": "uno",
"two": "dos",
},
ContextEvaluator: nil,
},
"context-aware": {
Key: "context-aware",
State: memprovider.Enabled,
DefaultVariant: "external",
Variants: map[string]interface{}{
"internal": "INTERNAL",
"external": "EXTERNAL",
},
ContextEvaluator: &ctxFunction,
},
}
16 changes: 4 additions & 12 deletions e2e/evaluation_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,21 @@ package e2e_test

import (
"context"
"github.com/open-feature/go-sdk/pkg/openfeature"
"github.com/open-feature/go-sdk/pkg/openfeature/memprovider"
"strings"
"testing"
"time"

flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg"
"github.com/open-feature/go-sdk/pkg/openfeature"
)

func setupFuzzClient(f *testing.F) *openfeature.Client {
f.Helper()

provider := flagd.NewProvider(flagd.WithPort(8013), flagd.WithoutCache())
err := openfeature.SetProvider(provider)
memoryProvider := memprovider.NewInMemoryProvider(map[string]memprovider.InMemoryFlag{})
err := openfeature.SetProvider(memoryProvider)
if err != nil {
f.Errorf("error setting up provider %v", err)
}

select {
case <-provider.IsReady():
case <-time.After(500 * time.Millisecond):
f.Fatal("provider not ready after 500 milliseconds")
}

return openfeature.NewClient("fuzzing")
}

Expand Down
Loading