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

Add unit and integration tests #6

Merged
merged 16 commits into from
Jan 23, 2024
Merged
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,4 @@ func main() {
}
// do something with the secret
}
```
To pass the service account token as an environment variable (`OP_SERVICE_ACCOUNT_TOKEN`), you can also use the `onepassword.NewServiceAccountClientFromEnv()` function.
```
95 changes: 95 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package onepassword

import (
"context"
"github.com/stretchr/testify/require"
"runtime"
"testing"

"github.com/stretchr/testify/assert"
)

func preTest() {
sharedCore = NewTestCore()
}

func TestNoToken(t *testing.T) {
preTest()
// missing token
_, err := NewClient(context.TODO(),
WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion))
assert.Equal(t, "cannot create a client without specifying a Service Account Token", err.Error())
}

func TestNoIntegrationName(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo("", DefaultIntegrationVersion))
assert.Equal(t, "cannot create a client without defining an app name and version. If you don't want to specify any, use the provided constants: 'DefaultIntegrationName', 'DefaultIntegrationVersion'", err.Error())
}

func TestInvalidIntegrationNameLength(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion))
assert.Equal(t, "integration name can't be longer than 40 characters", err.Error())
}

func TestInvalidIntegrationNameCharacters(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo("$", DefaultIntegrationVersion))
assert.Equal(t, "integration name can only contain digits, letters and allowed symbols", err.Error())
}

func TestNoIntegrationVersion(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo(DefaultIntegrationName, ""))
assert.Equal(t, "cannot create a client without defining an app name and version. If you don't want to specify any, use the provided constants: 'DefaultIntegrationName', 'DefaultIntegrationVersion'", err.Error())
}

func TestInvalidIntegrationVersionLength(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890"))
assert.Equal(t, "integration version can't be longer than 20 characters", err.Error())
}

func TestInvalidIntegrationVersionCharacters(t *testing.T) {
preTest()
token := "my_token"

_, err := NewClient(context.TODO(),
WithServiceAccountToken(token),
WithIntegrationInfo(DefaultIntegrationName, "$"))
assert.Equal(t, "integration version can only contain digits, letters and allowed symbols", err.Error())
}

func TestClientIsReleasedWhenGarbageCollected(t *testing.T) {
preTest()
testCore := NewTestCore()
sharedCore = testCore
_, err := NewClient(context.TODO(),
WithServiceAccountToken("test_token"),
WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion))
require.NoError(t, err)
assert.True(t, testCore.clientExists[0])
runtime.GC()
assert.False(t, testCore.clientExists[0])
}
24 changes: 24 additions & 0 deletions core.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,27 @@ func allowed1PHosts() []string {
"*.b5local.com",
}
}

type TestCore struct {
id uint64
clientExists map[uint64]bool
}

func NewTestCore() *TestCore {
return &TestCore{clientExists: make(map[uint64]bool)}
}

func (c TestCore) InitClient(config ClientConfig) (*uint64, error) {
c.clientExists[c.id] = true
c.id++
return &c.id, nil
}

func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) {
response := "secret"
return &response, nil
}

func (c TestCore) ReleaseClient(clientID uint64) {
c.clientExists[clientID] = false
}
81 changes: 81 additions & 0 deletions core_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package onepassword

import (
"context"
"sort"
"testing"

"github.com/stretchr/testify/assert"
)

func TestLoadWASM(t *testing.T) {
ctx := context.TODO()
value, _ := loadWASM(ctx)

// check only one module field
assert.Equal(t, 1, len(value.Modules))

// check ExportedFunctionsDefinitions names match (init_client, invoke, release_client)
list := [3]string{"init_client", "invoke", "release_client"}

count := 0
for _, x := range list {
for _, y := range value.Main.ExportedFunctionDefinitions() {
if x == y.Name() {
count++
}
}
}

assert.Equal(t, 3, count)

// check AllowedHosts field matches allowed1PHosts
pluginHosts := sort.StringSlice(value.AllowedHosts)
opHosts := sort.StringSlice(allowed1PHosts())

assert.Equal(t, len(pluginHosts), len(opHosts))

for x := range pluginHosts {
assert.Equal(t, pluginHosts[x], opHosts[x])
}
}

func TestInvalidClientConfig(t *testing.T) {
ctx := context.TODO()
core, _ := NewExtismCore(ctx)
config := NewDefaultConfig() // invalid without setting SAToken field
_, err := Core.InitClient(core, config)
assert.Equal(t, "invalid service account token", err.Error())
}

func TestInvalidInvoke(t *testing.T) {

validClientID := 0
validMethodName := ""
validParams := ""
invalidClientID := 0
invalidMethodName := ""
invalidParams := ""

ctx := context.TODO()
core, _ := NewExtismCore(ctx)

// invalid client id
invocation1 := Invocation{uint64(invalidClientID), validMethodName, validParams}
_, err1 := core.Invoke(invocation1)
println(err1.Error())

assert.Equal(t, "wrong method", err1.Error())

// invalid method name
invocation2 := Invocation{uint64(validClientID), invalidMethodName, validParams}
_, err2 := core.Invoke(invocation2)

assert.Equal(t, "wrong method", err2.Error())

// serialized params
invocation3 := Invocation{uint64(validClientID), validMethodName, invalidParams}
_, err3 := core.Invoke(invocation3)

assert.Equal(t, "wrong method", err3.Error())
}
11 changes: 10 additions & 1 deletion imported_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package onepassword

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/tetratelabs/wazero/api"
"testing"
)

func TestRandomFillFunc(t *testing.T) {
Expand All @@ -21,3 +22,11 @@ func TestRandomFillFunc(t *testing.T) {
assert.Equal(t, 1, len(stack))
assert.Equal(t, uint64(25089), stack[0])
}

func TestImportedFunctions(t *testing.T) {
// initial call
value := ImportedFunctions()

// check the returned function name is "random_fill_imported"
assert.Equal(t, "random_fill_imported", value[0].Name)
}
31 changes: 0 additions & 31 deletions integration_test.go

This file was deleted.

58 changes: 58 additions & 0 deletions integration_tests/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package integration_tests

import (
"context"
"os"
"testing"

onepassword "github.com/1password/1password-go-sdk"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// These tests were designed for CI/CD. If you want to run them locally you must make sure the following dependencies are in place:
// A valid (test) Service Account Token is set in the environment - export OP_SERVICE_ACCOUNT_TOKEN = ...
// Secret references and expected values are matching existing secrets in the test account.

func TestSecretRetrievalFromTestAccount(t *testing.T) {
token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN")

client, err := onepassword.NewClient(context.TODO(),
onepassword.WithServiceAccountToken(token),
onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion),
)
if err != nil {
panic(err)
}

secret, err := client.Secrets.Resolve("op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password")
if err != nil {
panic(err)
}

assert.Equal(t, "test_password", *secret)
}

func TestInitClientIncrement(t *testing.T) {

token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN")

ctx := context.TODO()
core, _ := onepassword.NewExtismCore(ctx)
config := onepassword.NewDefaultConfig()
config.SAToken = token
config.IntegrationName = "name"
config.IntegrationVersion = "version"

value1, err1 := core.InitClient(config)
require.NoError(t, err1)
value2, err2 := core.InitClient(config)
require.NoError(t, err2)
value3, err3 := core.InitClient(config)
require.NoError(t, err3)

assert.Equal(t, uint64(0), *value1)
assert.Equal(t, uint64(1), *value2)
assert.Equal(t, uint64(2), *value3)
}
Loading