From f795b8b6b703b1fe2637b54a2964ddf8c3a67552 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Thu, 18 Jan 2024 20:53:41 -0500 Subject: [PATCH 01/16] partially completed test cases --- client_test.go | 93 ++++++++++++++++++++++++++++ core_test.go | 155 +++++++++++++++++++++++++++++++++++++++++++++++ imported_test.go | 10 +++ 3 files changed, 258 insertions(+) create mode 100644 client_test.go create mode 100644 core_test.go diff --git a/client_test.go b/client_test.go new file mode 100644 index 0000000..b6c2898 --- /dev/null +++ b/client_test.go @@ -0,0 +1,93 @@ +package onepassword + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" +) + +// invalid name/version test cases may belong in integration_test.go +// currently these tests fail correctly, but they have incorrect tokens, so the accuracy of these fails is in question + +func TestNoToken(t *testing.T) { + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + // missing token + _, err = clientFactory.NewClient( + WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestNoIntegrationName(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameLength(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameCharacters(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("$", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestNoIntegrationVersion(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionLength(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionCharacters(t *testing.T) { + token := "" + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "$")) + require.Error(t, err) +} diff --git a/core_test.go b/core_test.go new file mode 100644 index 0000000..91c3c79 --- /dev/null +++ b/core_test.go @@ -0,0 +1,155 @@ +package onepassword + +import ( + "context" + "sort" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestLoadWASM(t *testing.T) { + ctx := context.TODO() + value, _ := loadWASM(ctx) + + /* + The following three lines of code are commented out to pass the test case + I am unsure if checking the return type of loadWASM() is necessary + */ + + // check return type is extism.Plugin + // if reflect.TypeOf(value).Kind() != reflect.TypeOf(extism.NewPlugin).Kind() { + // t.Fatal("loadWASM returns ", reflect.TypeOf(*value).Kind(), ", expected ", reflect.TypeOf(extism.NewPlugin).Kind()) + // } + + // check only one module field + if len(value.Modules) != 1 { + t.Fatal("1 extism plugin module expected, ", len(value.Modules), " instead") + } + // 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++ + } + } + } + + if count != len(list) { + t.Fatal("ExportedFunctionDefinitions expected ", len(list), " functions, ", count, " were counted instead") + } + + // check AllowedHosts field matches allowed1PHosts + plugin_hosts := sort.StringSlice(value.AllowedHosts) + op_hosts := sort.StringSlice(allowed1PHosts()) + + if len(plugin_hosts) != len(op_hosts) { + t.Fatal("Expected AllowedHosts is different from actual AllowedHosts") + } + + for x := range plugin_hosts { + if plugin_hosts[x] != op_hosts[x] { + t.Fatal("Expected AllowedHosts is different from actual AllowedHosts") + } + } +} + +func TestNewClientId(t *testing.T) { + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config1 := ClientConfig{} //TODO: make valid config + config2 := ClientConfig{} //TODO: make valid config + value1, _ := Core.InitClient(core, config1) + value2, _ := Core.InitClient(core, config2) + if *value1 == *value2 { + t.Fatalf("new client id not created") + } +} + +func TestInitClientIncrement(t *testing.T) { + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config := ClientConfig{} //TODO: make valid config + value1, _ := Core.InitClient(core, config) + value2, _ := Core.InitClient(core, config) + value3, _ := Core.InitClient(core, config) + if *value1 != 0 || *value2 != 1 || *value3 != 2 { + t.Fatalf("client id does not increment") + } +} + +func TestInvalidClientConfig(t *testing.T) { + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config := ClientConfig{} //TODO: make invalid config + _, err := Core.InitClient(core, config) + require.Error(t, err) +} + +func TestInvokeReturnsSecret(t *testing.T) { + + clientId := 0 + methodName := "" + params := "" + + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + invocation := Invocation{uint64(clientId), methodName, params} + invoke, err := Core.Invoke(core, invocation) + require.NoError(t, err) + + //TODO: setup on valid test secret reference + *invoke = "" // just here to remove error temporarily +} + +func TestInvalidInvoke(t *testing.T) { + + valid_clientId := 0 + valid_methodName := "" + valid_params := "" + invalid_clientId := 0 + invalid_methodName := "" + invalid_params := "" + + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + + // invalid client id + invocation1 := Invocation{uint64(invalid_clientId), valid_methodName, valid_params} + _, err1 := Core.Invoke(core, invocation1) + + require.Error(t, err1) + + // invalid method name + invocation2 := Invocation{uint64(valid_clientId), invalid_methodName, valid_params} + _, err2 := Core.Invoke(core, invocation2) + + require.Error(t, err2) + + // serialized params + invocation3 := Invocation{uint64(valid_clientId), valid_methodName, invalid_params} + _, err3 := Core.Invoke(core, invocation3) + + require.Error(t, err3) +} + +func TestReleaseClient(t *testing.T) { + // ensure latest id is not zero + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config := ClientConfig{} //TODO: make valid config + Core.InitClient(core, config) + latest, _ := Core.InitClient(core, config) + + // release memory + Core.ReleaseClient(core, *latest) + + // check next initialization has id zero + value, _ := Core.InitClient(core, config) + if *value != 0 { + t.Fatal("client id after memory release expected to be 0, is ", *value, " instead") + } +} diff --git a/imported_test.go b/imported_test.go index f01796b..f73f956 100644 --- a/imported_test.go +++ b/imported_test.go @@ -21,3 +21,13 @@ 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" + if value[0].Name != "random_fill_imported" { + t.Fatal("ImportedFunctions() expected to return function 'random_fill_imported', returns ", value[0].Name, " instead") + } +} From 7aad95a8b6ddd5f6f582131a77ffff594f4f87d9 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 19 Jan 2024 09:50:53 -0500 Subject: [PATCH 02/16] added one integration test for initializing three clients --- core_test.go | 28 ---------------------------- integration_test.go | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/core_test.go b/core_test.go index 91c3c79..c7ffaba 100644 --- a/core_test.go +++ b/core_test.go @@ -69,18 +69,6 @@ func TestNewClientId(t *testing.T) { } } -func TestInitClientIncrement(t *testing.T) { - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - config := ClientConfig{} //TODO: make valid config - value1, _ := Core.InitClient(core, config) - value2, _ := Core.InitClient(core, config) - value3, _ := Core.InitClient(core, config) - if *value1 != 0 || *value2 != 1 || *value3 != 2 { - t.Fatalf("client id does not increment") - } -} - func TestInvalidClientConfig(t *testing.T) { ctx := context.TODO() core, _ := NewExtismCore(ctx) @@ -89,22 +77,6 @@ func TestInvalidClientConfig(t *testing.T) { require.Error(t, err) } -func TestInvokeReturnsSecret(t *testing.T) { - - clientId := 0 - methodName := "" - params := "" - - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - invocation := Invocation{uint64(clientId), methodName, params} - invoke, err := Core.Invoke(core, invocation) - require.NoError(t, err) - - //TODO: setup on valid test secret reference - *invoke = "" // just here to remove error temporarily -} - func TestInvalidInvoke(t *testing.T) { valid_clientId := 0 diff --git a/integration_test.go b/integration_test.go index b34535d..65a247d 100644 --- a/integration_test.go +++ b/integration_test.go @@ -2,9 +2,11 @@ package onepassword import ( "context" - "github.com/stretchr/testify/assert" "os" "testing" + + "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: @@ -29,3 +31,26 @@ func TestSecretRetrievalFromTestAccount(t *testing.T) { assert.Equal(t, "test_password", *secret) } + +func TestInitClientIncrement(t *testing.T) { + + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config := NewDefaultConfig() + config.SAToken = token + config.IntegrationName = "name" + config.IntegrationVersion = "version" + + value1, err1 := Core.InitClient(core, config) + require.NoError(t, err1) + value2, err2 := Core.InitClient(core, config) + require.NoError(t, err2) + value3, err3 := Core.InitClient(core, config) + require.NoError(t, err3) + + assert.Equal(t, 0, value1) + assert.Equal(t, 1, value2) + assert.Equal(t, 2, value3) +} From a265341e42d051fce100c7a6226ef2d0241b36b1 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sun, 21 Jan 2024 19:11:31 -0500 Subject: [PATCH 03/16] more test cases finished --- client_test.go | 72 ---------------------------- core_test.go | 38 +++------------ integration_test.go | 111 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 114 insertions(+), 107 deletions(-) diff --git a/client_test.go b/client_test.go index b6c2898..4895d92 100644 --- a/client_test.go +++ b/client_test.go @@ -19,75 +19,3 @@ func TestNoToken(t *testing.T) { WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion)) require.Error(t, err) } - -func TestNoIntegrationName(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestInvalidIntegrationNameLength(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestInvalidIntegrationNameCharacters(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("$", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestNoIntegrationVersion(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "")) - require.Error(t, err) -} - -func TestInvalidIntegrationVersionLength(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) - require.Error(t, err) -} - -func TestInvalidIntegrationVersionCharacters(t *testing.T) { - token := "" - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "$")) - require.Error(t, err) -} diff --git a/core_test.go b/core_test.go index c7ffaba..71b5b1d 100644 --- a/core_test.go +++ b/core_test.go @@ -5,6 +5,7 @@ import ( "sort" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -12,16 +13,6 @@ func TestLoadWASM(t *testing.T) { ctx := context.TODO() value, _ := loadWASM(ctx) - /* - The following three lines of code are commented out to pass the test case - I am unsure if checking the return type of loadWASM() is necessary - */ - - // check return type is extism.Plugin - // if reflect.TypeOf(value).Kind() != reflect.TypeOf(extism.NewPlugin).Kind() { - // t.Fatal("loadWASM returns ", reflect.TypeOf(*value).Kind(), ", expected ", reflect.TypeOf(extism.NewPlugin).Kind()) - // } - // check only one module field if len(value.Modules) != 1 { t.Fatal("1 extism plugin module expected, ", len(value.Modules), " instead") @@ -46,33 +37,17 @@ func TestLoadWASM(t *testing.T) { plugin_hosts := sort.StringSlice(value.AllowedHosts) op_hosts := sort.StringSlice(allowed1PHosts()) - if len(plugin_hosts) != len(op_hosts) { - t.Fatal("Expected AllowedHosts is different from actual AllowedHosts") - } + assert.Equal(t, len(plugin_hosts), len(op_hosts)) for x := range plugin_hosts { - if plugin_hosts[x] != op_hosts[x] { - t.Fatal("Expected AllowedHosts is different from actual AllowedHosts") - } - } -} - -func TestNewClientId(t *testing.T) { - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - config1 := ClientConfig{} //TODO: make valid config - config2 := ClientConfig{} //TODO: make valid config - value1, _ := Core.InitClient(core, config1) - value2, _ := Core.InitClient(core, config2) - if *value1 == *value2 { - t.Fatalf("new client id not created") + assert.Equal(t, plugin_hosts[x], op_hosts[x]) } } func TestInvalidClientConfig(t *testing.T) { ctx := context.TODO() core, _ := NewExtismCore(ctx) - config := ClientConfig{} //TODO: make invalid config + config := NewDefaultConfig() // invalid without setting SAToken field _, err := Core.InitClient(core, config) require.Error(t, err) } @@ -92,6 +67,7 @@ func TestInvalidInvoke(t *testing.T) { // invalid client id invocation1 := Invocation{uint64(invalid_clientId), valid_methodName, valid_params} _, err1 := Core.Invoke(core, invocation1) + println(err1.Error()) require.Error(t, err1) @@ -121,7 +97,5 @@ func TestReleaseClient(t *testing.T) { // check next initialization has id zero value, _ := Core.InitClient(core, config) - if *value != 0 { - t.Fatal("client id after memory release expected to be 0, is ", *value, " instead") - } + assert.Equal(t, 0, *value) } diff --git a/integration_test.go b/integration_test.go index 65a247d..45431cd 100644 --- a/integration_test.go +++ b/integration_test.go @@ -50,7 +50,112 @@ func TestInitClientIncrement(t *testing.T) { value3, err3 := Core.InitClient(core, config) require.NoError(t, err3) - assert.Equal(t, 0, value1) - assert.Equal(t, 1, value2) - assert.Equal(t, 2, value3) + assert.Equal(t, uint64(0), *value1) + assert.Equal(t, uint64(1), *value2) + assert.Equal(t, uint64(2), *value3) +} + +func TestNewClientId(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config1 := NewDefaultConfig() + config1.SAToken = token + config1.IntegrationName = "name" + config1.IntegrationVersion = "version" + config2 := NewDefaultConfig() + config2.SAToken = token + config2.IntegrationName = "name" + config2.IntegrationVersion = "version" + value1, _ := Core.InitClient(core, config1) + value2, _ := Core.InitClient(core, config2) + assert.NotEqual(t, *value1, *value2) +} + +// +// invalid NewClient calls +// + +func TestNoIntegrationNameOrVersion(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("", "")) + require.Error(t, err) +} + +func TestNoIntegrationName(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameLength(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameCharacters(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("$", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestNoIntegrationVersion(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionLength(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionCharacters(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory, err := NewClientFactory(context.TODO()) + require.NoError(t, err) + + _, err = clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "$")) + require.Error(t, err) } From 59747abf41a9ab24916ff56e40d4b9fab7f695d5 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sun, 21 Jan 2024 19:15:06 -0500 Subject: [PATCH 04/16] type cast fix --- core_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core_test.go b/core_test.go index 71b5b1d..3befb7d 100644 --- a/core_test.go +++ b/core_test.go @@ -97,5 +97,5 @@ func TestReleaseClient(t *testing.T) { // check next initialization has id zero value, _ := Core.InitClient(core, config) - assert.Equal(t, 0, *value) + assert.Equal(t, uint64(0), *value) } From 47c252e92ea183db3a39ce8f46f1a3556b900b78 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sun, 21 Jan 2024 19:22:44 -0500 Subject: [PATCH 05/16] moved release client test to integration file --- core_test.go | 16 ---------------- imported_test.go | 6 +++--- integration_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/core_test.go b/core_test.go index 3befb7d..b927cdc 100644 --- a/core_test.go +++ b/core_test.go @@ -83,19 +83,3 @@ func TestInvalidInvoke(t *testing.T) { require.Error(t, err3) } - -func TestReleaseClient(t *testing.T) { - // ensure latest id is not zero - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - config := ClientConfig{} //TODO: make valid config - Core.InitClient(core, config) - latest, _ := Core.InitClient(core, config) - - // release memory - Core.ReleaseClient(core, *latest) - - // check next initialization has id zero - value, _ := Core.InitClient(core, config) - assert.Equal(t, uint64(0), *value) -} diff --git a/imported_test.go b/imported_test.go index f73f956..adacab6 100644 --- a/imported_test.go +++ b/imported_test.go @@ -4,6 +4,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/tetratelabs/wazero/api" "testing" + + "github.com/stretchr/testify/assert" ) func TestRandomFillFunc(t *testing.T) { @@ -27,7 +29,5 @@ func TestImportedFunctions(t *testing.T) { value := ImportedFunctions() // check the returned function name is "random_fill_imported" - if value[0].Name != "random_fill_imported" { - t.Fatal("ImportedFunctions() expected to return function 'random_fill_imported', returns ", value[0].Name, " instead") - } + assert.Equal(t, "random_fill_imported", value[0].Name) } diff --git a/integration_test.go b/integration_test.go index 45431cd..52ec617 100644 --- a/integration_test.go +++ b/integration_test.go @@ -159,3 +159,28 @@ func TestInvalidIntegrationVersionCharacters(t *testing.T) { WithIntegrationInfo(DefaultIntegrationName, "$")) require.Error(t, err) } + +// +// end of invalid NewClient Calls +// + +func TestReleaseClient(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + // ensure latest id is not zero + ctx := context.TODO() + core, _ := NewExtismCore(ctx) + config := NewDefaultConfig() + config.SAToken = token + config.IntegrationName = "name" + config.IntegrationVersion = "version" + Core.InitClient(core, config) + latest, _ := Core.InitClient(core, config) + + // release memory + Core.ReleaseClient(core, *latest) + + // check next initialization has id zero + value, _ := Core.InitClient(core, config) + assert.Equal(t, uint64(0), *value) +} From 3f30d1fdda553b984e102f977551fa2fe0629932 Mon Sep 17 00:00:00 2001 From: AndyTitu Date: Mon, 22 Jan 2024 13:26:29 +0100 Subject: [PATCH 06/16] Rebase --- imported_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imported_test.go b/imported_test.go index adacab6..72f7bad 100644 --- a/imported_test.go +++ b/imported_test.go @@ -1,11 +1,10 @@ package onepassword import ( - "github.com/stretchr/testify/assert" - "github.com/tetratelabs/wazero/api" "testing" "github.com/stretchr/testify/assert" + "github.com/tetratelabs/wazero/api" ) func TestRandomFillFunc(t *testing.T) { From d4818af09830954731d4e3f951c8f465a01fda34 Mon Sep 17 00:00:00 2001 From: AndyTitu Date: Mon, 22 Jan 2024 13:47:28 +0100 Subject: [PATCH 07/16] Separate integration tests from unit tests --- README.md | 3 +- client_test.go | 105 ++++++++++++++++++++++++-- integration_tests/integration_test.go | 84 +++++++++++++++++++++ 3 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 integration_tests/integration_test.go diff --git a/README.md b/README.md index f0af0ea..b1e12a1 100644 --- a/README.md +++ b/README.md @@ -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. +``` \ No newline at end of file diff --git a/client_test.go b/client_test.go index 4895d92..e96f505 100644 --- a/client_test.go +++ b/client_test.go @@ -1,21 +1,112 @@ package onepassword import ( - "context" + "os" "testing" "github.com/stretchr/testify/require" ) -// invalid name/version test cases may belong in integration_test.go -// currently these tests fail correctly, but they have incorrect tokens, so the accuracy of these fails is in question - func TestNoToken(t *testing.T) { - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) + clientFactory := NewTestClientFactory() // missing token - _, err = clientFactory.NewClient( + _, err := clientFactory.NewClient( WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion)) require.Error(t, err) } + +func TestNoIntegrationNameOrVersion(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("", "")) + require.Error(t, err) +} + +func TestNoIntegrationName(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameLength(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestInvalidIntegrationNameCharacters(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo("$", DefaultIntegrationVersion)) + require.Error(t, err) +} + +func TestNoIntegrationVersion(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionLength(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) + require.Error(t, err) +} + +func TestInvalidIntegrationVersionCharacters(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + clientFactory := NewTestClientFactory() + + _, err := clientFactory.NewClient( + WithServiceAccountToken(token), + WithIntegrationInfo(DefaultIntegrationName, "$")) + require.Error(t, err) +} + +func NewTestClientFactory() *ClientFactory { + return &ClientFactory{core: TestCore{}} +} + +type TestCore struct{} + +func (c TestCore) InitClient(config ClientConfig) (*uint64, error) { + var id uint64 + return &id, nil +} + +func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { + response := "secret" + return &response, nil +} + +func (c TestCore) ReleaseClient(clientID uint64) {} diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go new file mode 100644 index 0000000..8b4f786 --- /dev/null +++ b/integration_tests/integration_test.go @@ -0,0 +1,84 @@ +package integration_tests + +import ( + "context" + onepassword "github.com/1password/1password-go-sdk" + "os" + "testing" + + "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") + + clientFactory, err := onepassword.NewClientFactory(context.TODO()) + if err != nil { + panic(err) + } + + client, err := clientFactory.NewClient( + 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) +} + +func TestReleaseClient(t *testing.T) { + token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + + // ensure latest id is not zero + ctx := context.TODO() + core, _ := onepassword.NewExtismCore(ctx) + config := onepassword.NewDefaultConfig() + config.SAToken = token + config.IntegrationName = "name" + config.IntegrationVersion = "version" + _, err := core.InitClient(config) + require.NoError(t, err) + latest, _ := core.InitClient(config) + + // release memory + core.ReleaseClient(*latest) + + // check next initialization has id zero + value, _ := core.InitClient(config) + assert.Equal(t, uint64(0), *value) +} From 5778cf251a5f0a19d0d28529dd4cb511422f1518 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 22 Jan 2024 10:00:35 -0500 Subject: [PATCH 08/16] resolved conversation errors --- client_test.go | 40 ++++++++------------- core_test.go | 52 +++++++++++++-------------- integration_tests/integration_test.go | 3 +- 3 files changed, 40 insertions(+), 55 deletions(-) diff --git a/client_test.go b/client_test.go index e96f505..ac61460 100644 --- a/client_test.go +++ b/client_test.go @@ -1,10 +1,9 @@ package onepassword import ( - "os" "testing" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) func TestNoToken(t *testing.T) { @@ -13,84 +12,73 @@ func TestNoToken(t *testing.T) { // missing token _, err := clientFactory.NewClient( WithIntegrationInfo(DefaultIntegrationName, DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestNoIntegrationNameOrVersion(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("", "")) - require.Error(t, err) + assert.Equal(t, "cannot create a client without specifying a Service Account Token", err.Error()) } func TestNoIntegrationName(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo("", DefaultIntegrationVersion)) - require.Error(t, err) + 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) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) - require.Error(t, err) + assert.Equal(t, "integration name can't be longer than 40 characters", err.Error()) } func TestInvalidIntegrationNameCharacters(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo("$", DefaultIntegrationVersion)) - require.Error(t, err) + assert.Equal(t, "integration name can only contain digits, letters and allowed symbols", err.Error()) } func TestNoIntegrationVersion(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo(DefaultIntegrationName, "")) - require.Error(t, err) + 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) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) - require.Error(t, err) + assert.Equal(t, "integration version can't be longer than 20 characters", err.Error()) } func TestInvalidIntegrationVersionCharacters(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") + token := "my_token" clientFactory := NewTestClientFactory() _, err := clientFactory.NewClient( WithServiceAccountToken(token), WithIntegrationInfo(DefaultIntegrationName, "$")) - require.Error(t, err) + assert.Equal(t, "integration version can only contain digits, letters and allowed symbols", err.Error()) } func NewTestClientFactory() *ClientFactory { diff --git a/core_test.go b/core_test.go index b927cdc..a438252 100644 --- a/core_test.go +++ b/core_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestLoadWASM(t *testing.T) { @@ -14,9 +13,8 @@ func TestLoadWASM(t *testing.T) { value, _ := loadWASM(ctx) // check only one module field - if len(value.Modules) != 1 { - t.Fatal("1 extism plugin module expected, ", len(value.Modules), " instead") - } + assert.Equal(t, 1, len(value.Modules)) + // check ExportedFunctionsDefinitions names match (init_client, invoke, release_client) list := [3]string{"init_client", "invoke", "release_client"} @@ -29,18 +27,16 @@ func TestLoadWASM(t *testing.T) { } } - if count != len(list) { - t.Fatal("ExportedFunctionDefinitions expected ", len(list), " functions, ", count, " were counted instead") - } + assert.Equal(t, 3, count) // check AllowedHosts field matches allowed1PHosts - plugin_hosts := sort.StringSlice(value.AllowedHosts) - op_hosts := sort.StringSlice(allowed1PHosts()) + pluginHosts := sort.StringSlice(value.AllowedHosts) + opHosts := sort.StringSlice(allowed1PHosts()) - assert.Equal(t, len(plugin_hosts), len(op_hosts)) + assert.Equal(t, len(pluginHosts), len(opHosts)) - for x := range plugin_hosts { - assert.Equal(t, plugin_hosts[x], op_hosts[x]) + for x := range pluginHosts { + assert.Equal(t, pluginHosts[x], opHosts[x]) } } @@ -49,37 +45,37 @@ func TestInvalidClientConfig(t *testing.T) { core, _ := NewExtismCore(ctx) config := NewDefaultConfig() // invalid without setting SAToken field _, err := Core.InitClient(core, config) - require.Error(t, err) + assert.Equal(t, "invalid service account token", err.Error()) } func TestInvalidInvoke(t *testing.T) { - valid_clientId := 0 - valid_methodName := "" - valid_params := "" - invalid_clientId := 0 - invalid_methodName := "" - invalid_params := "" + validClientID := 0 + validMethodName := "" + validParams := "" + invalidClientID := 0 + invalidMethodName := "" + invalidParams := "" ctx := context.TODO() core, _ := NewExtismCore(ctx) // invalid client id - invocation1 := Invocation{uint64(invalid_clientId), valid_methodName, valid_params} - _, err1 := Core.Invoke(core, invocation1) + invocation1 := Invocation{uint64(invalidClientID), validMethodName, validParams} + _, err1 := core.Invoke(invocation1) println(err1.Error()) - require.Error(t, err1) + assert.Equal(t, "wrong method", err1.Error()) // invalid method name - invocation2 := Invocation{uint64(valid_clientId), invalid_methodName, valid_params} - _, err2 := Core.Invoke(core, invocation2) + invocation2 := Invocation{uint64(validClientID), invalidMethodName, validParams} + _, err2 := core.Invoke(invocation2) - require.Error(t, err2) + assert.Equal(t, "wrong method", err2.Error()) // serialized params - invocation3 := Invocation{uint64(valid_clientId), valid_methodName, invalid_params} - _, err3 := Core.Invoke(core, invocation3) + invocation3 := Invocation{uint64(validClientID), validMethodName, invalidParams} + _, err3 := core.Invoke(invocation3) - require.Error(t, err3) + assert.Equal(t, "wrong method", err3.Error()) } diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index 8b4f786..791fd37 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -2,10 +2,11 @@ package integration_tests import ( "context" - onepassword "github.com/1password/1password-go-sdk" "os" "testing" + onepassword "github.com/1password/1password-go-sdk" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) From 8a46f8e39f44e78d4be5a5a6e61eced211f15d94 Mon Sep 17 00:00:00 2001 From: AndyTitu Date: Mon, 22 Jan 2024 16:48:15 +0100 Subject: [PATCH 09/16] Move release client test in client_test --- client_test.go | 69 +++++----- core.go | 24 ++++ integration_test.go | 186 -------------------------- integration_tests/integration_test.go | 29 +--- 4 files changed, 57 insertions(+), 251 deletions(-) delete mode 100644 integration_test.go diff --git a/client_test.go b/client_test.go index ac61460..cc43bc0 100644 --- a/client_test.go +++ b/client_test.go @@ -1,100 +1,95 @@ package onepassword import ( + "context" + "github.com/stretchr/testify/require" + "runtime" "testing" "github.com/stretchr/testify/assert" ) -func TestNoToken(t *testing.T) { - clientFactory := NewTestClientFactory() +func preTest() { + sharedCore = NewTestCore() +} +func TestNoToken(t *testing.T) { + preTest() // missing token - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, 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" - clientFactory := NewTestClientFactory() - - _, err := clientFactory.NewClient( + _, err := NewClient(context.TODO(), WithServiceAccountToken(token), WithIntegrationInfo(DefaultIntegrationName, "$")) assert.Equal(t, "integration version can only contain digits, letters and allowed symbols", err.Error()) } -func NewTestClientFactory() *ClientFactory { - return &ClientFactory{core: TestCore{}} -} - -type TestCore struct{} - -func (c TestCore) InitClient(config ClientConfig) (*uint64, error) { - var id uint64 - return &id, nil -} - -func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { - response := "secret" - return &response, nil +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]) } - -func (c TestCore) ReleaseClient(clientID uint64) {} diff --git a/core.go b/core.go index 0fd47bf..23194b7 100644 --- a/core.go +++ b/core.go @@ -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 +} diff --git a/integration_test.go b/integration_test.go deleted file mode 100644 index 52ec617..0000000 --- a/integration_test.go +++ /dev/null @@ -1,186 +0,0 @@ -package onepassword - -import ( - "context" - "os" - "testing" - - "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 := NewClient(context.TODO(), - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, 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, _ := NewExtismCore(ctx) - config := NewDefaultConfig() - config.SAToken = token - config.IntegrationName = "name" - config.IntegrationVersion = "version" - - value1, err1 := Core.InitClient(core, config) - require.NoError(t, err1) - value2, err2 := Core.InitClient(core, config) - require.NoError(t, err2) - value3, err3 := Core.InitClient(core, config) - require.NoError(t, err3) - - assert.Equal(t, uint64(0), *value1) - assert.Equal(t, uint64(1), *value2) - assert.Equal(t, uint64(2), *value3) -} - -func TestNewClientId(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - config1 := NewDefaultConfig() - config1.SAToken = token - config1.IntegrationName = "name" - config1.IntegrationVersion = "version" - config2 := NewDefaultConfig() - config2.SAToken = token - config2.IntegrationName = "name" - config2.IntegrationVersion = "version" - value1, _ := Core.InitClient(core, config1) - value2, _ := Core.InitClient(core, config2) - assert.NotEqual(t, *value1, *value2) -} - -// -// invalid NewClient calls -// - -func TestNoIntegrationNameOrVersion(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("", "")) - require.Error(t, err) -} - -func TestNoIntegrationName(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestInvalidIntegrationNameLength(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("12345678901234567890123456789012345678901234567890", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestInvalidIntegrationNameCharacters(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo("$", DefaultIntegrationVersion)) - require.Error(t, err) -} - -func TestNoIntegrationVersion(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "")) - require.Error(t, err) -} - -func TestInvalidIntegrationVersionLength(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "12345678901234567890123456789012345678901234567890")) - require.Error(t, err) -} - -func TestInvalidIntegrationVersionCharacters(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - clientFactory, err := NewClientFactory(context.TODO()) - require.NoError(t, err) - - _, err = clientFactory.NewClient( - WithServiceAccountToken(token), - WithIntegrationInfo(DefaultIntegrationName, "$")) - require.Error(t, err) -} - -// -// end of invalid NewClient Calls -// - -func TestReleaseClient(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - // ensure latest id is not zero - ctx := context.TODO() - core, _ := NewExtismCore(ctx) - config := NewDefaultConfig() - config.SAToken = token - config.IntegrationName = "name" - config.IntegrationVersion = "version" - Core.InitClient(core, config) - latest, _ := Core.InitClient(core, config) - - // release memory - Core.ReleaseClient(core, *latest) - - // check next initialization has id zero - value, _ := Core.InitClient(core, config) - assert.Equal(t, uint64(0), *value) -} diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index 791fd37..840d6de 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -18,12 +18,7 @@ import ( func TestSecretRetrievalFromTestAccount(t *testing.T) { token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - clientFactory, err := onepassword.NewClientFactory(context.TODO()) - if err != nil { - panic(err) - } - - client, err := clientFactory.NewClient( + client, err := onepassword.NewClient(context.TODO(), onepassword.WithServiceAccountToken(token), onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion), ) @@ -61,25 +56,3 @@ func TestInitClientIncrement(t *testing.T) { assert.Equal(t, uint64(1), *value2) assert.Equal(t, uint64(2), *value3) } - -func TestReleaseClient(t *testing.T) { - token := os.Getenv("OP_SERVICE_ACCOUNT_TOKEN") - - // ensure latest id is not zero - ctx := context.TODO() - core, _ := onepassword.NewExtismCore(ctx) - config := onepassword.NewDefaultConfig() - config.SAToken = token - config.IntegrationName = "name" - config.IntegrationVersion = "version" - _, err := core.InitClient(config) - require.NoError(t, err) - latest, _ := core.InitClient(config) - - // release memory - core.ReleaseClient(*latest) - - // check next initialization has id zero - value, _ := core.InitClient(config) - assert.Equal(t, uint64(0), *value) -} From 030f249b4afadff7de12e103b8f28770fc81fc64 Mon Sep 17 00:00:00 2001 From: AndyTitu Date: Mon, 22 Jan 2024 17:44:05 +0100 Subject: [PATCH 10/16] Remove GC test for now --- client.go | 1 - client_test.go | 39 ++++++++++++++++++++++++--------------- core.go | 24 ------------------------ 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/client.go b/client.go index b279172..6ebec40 100644 --- a/client.go +++ b/client.go @@ -89,7 +89,6 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) { } client.Secrets = NewSecretsSource(*clientID, sharedCore) - runtime.SetFinalizer(&client, func(f *Client) { sharedCore.ReleaseClient(*clientID) }) diff --git a/client_test.go b/client_test.go index cc43bc0..eb32038 100644 --- a/client_test.go +++ b/client_test.go @@ -2,11 +2,8 @@ package onepassword import ( "context" - "github.com/stretchr/testify/require" - "runtime" - "testing" - "github.com/stretchr/testify/assert" + "testing" ) func preTest() { @@ -81,15 +78,27 @@ func TestInvalidIntegrationVersionCharacters(t *testing.T) { 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]) +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 + res := c.id + c.id++ + return &res, nil +} + +func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { + response := "secret" + return &response, nil +} + +func (c TestCore) ReleaseClient(clientID uint64) { + c.clientExists[clientID] = false } diff --git a/core.go b/core.go index 23194b7..0fd47bf 100644 --- a/core.go +++ b/core.go @@ -131,27 +131,3 @@ 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 -} From 54cd550b97f6263d90e63eab39560bcf7b425c51 Mon Sep 17 00:00:00 2001 From: AndyTitu Date: Mon, 22 Jan 2024 17:50:09 +0100 Subject: [PATCH 11/16] Simplify test core for now --- client_test.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/client_test.go b/client_test.go index eb32038..5fff436 100644 --- a/client_test.go +++ b/client_test.go @@ -7,7 +7,7 @@ import ( ) func preTest() { - sharedCore = NewTestCore() + sharedCore = TestCore{} } func TestNoToken(t *testing.T) { @@ -79,18 +79,10 @@ func TestInvalidIntegrationVersionCharacters(t *testing.T) { } 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 - res := c.id - c.id++ + res := uint64(0) return &res, nil } @@ -99,6 +91,4 @@ func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { return &response, nil } -func (c TestCore) ReleaseClient(clientID uint64) { - c.clientExists[clientID] = false -} +func (c TestCore) ReleaseClient(clientID uint64) {} From a7ed50419eaded0ca71965d6d6fa2aa41d450fde Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 22 Jan 2024 14:14:11 -0500 Subject: [PATCH 12/16] updated test cases --- client_test.go | 7 +++- core_test.go | 32 --------------- integration_tests/integration_test.go | 56 ++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/client_test.go b/client_test.go index 5fff436..d26d690 100644 --- a/client_test.go +++ b/client_test.go @@ -2,8 +2,9 @@ package onepassword import ( "context" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func preTest() { @@ -92,3 +93,7 @@ func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { } func (c TestCore) ReleaseClient(clientID uint64) {} + +func TestGarbageCollectorReleasesClient(t *testing.T) { + +} diff --git a/core_test.go b/core_test.go index a438252..81121b6 100644 --- a/core_test.go +++ b/core_test.go @@ -47,35 +47,3 @@ func TestInvalidClientConfig(t *testing.T) { _, 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()) -} diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index 840d6de..68bda7e 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -22,14 +22,10 @@ func TestSecretRetrievalFromTestAccount(t *testing.T) { onepassword.WithServiceAccountToken(token), onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion), ) - if err != nil { - panic(err) - } + require.NoError(t, err) secret, err := client.Secrets.Resolve("op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password") - if err != nil { - panic(err) - } + require.NoError(t, err) assert.Equal(t, "test_password", *secret) } @@ -56,3 +52,51 @@ func TestInitClientIncrement(t *testing.T) { assert.Equal(t, uint64(1), *value2) assert.Equal(t, uint64(2), *value3) } + +func TestInvalidInvoke(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" + + value, _ := core.InitClient(config) + + client, err := onepassword.NewClient(context.TODO(), + onepassword.WithServiceAccountToken(token), + onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion), + ) + require.NoError(t, err) + + secret, err := client.Secrets.Resolve("op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password") + require.NoError(t, err) + + validClientID := *value + validMethodName := "Resolve" + validParams := *secret + invalidClientID := -1 + invalidMethodName := "" + invalidParams := "" + + // invalid client id + invocation1 := onepassword.Invocation{ClientID: uint64(invalidClientID), MethodName: validMethodName, SerializedParams: validParams} + _, err1 := core.Invoke(invocation1) + + assert.Equal(t, "wrong method", err1.Error()) + + // invalid method name + invocation2 := onepassword.Invocation{ClientID: uint64(validClientID), MethodName: invalidMethodName, SerializedParams: validParams} + _, err2 := core.Invoke(invocation2) + + assert.Equal(t, "wrong method", err2.Error()) + + // invalid serialized params + invocation3 := onepassword.Invocation{ClientID: uint64(validClientID), MethodName: validMethodName, SerializedParams: invalidParams} + _, err3 := core.Invoke(invocation3) + + assert.Equal(t, "wrong method", err3.Error()) +} From c8c4a84d597eab885c3ae41970bdcad7bef903d5 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 22 Jan 2024 14:15:50 -0500 Subject: [PATCH 13/16] updated invocation error messages --- integration_tests/integration_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index 68bda7e..bd69d31 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -86,7 +86,7 @@ func TestInvalidInvoke(t *testing.T) { invocation1 := onepassword.Invocation{ClientID: uint64(invalidClientID), MethodName: validMethodName, SerializedParams: validParams} _, err1 := core.Invoke(invocation1) - assert.Equal(t, "wrong method", err1.Error()) + assert.Equal(t, "invalid client id", err1.Error()) // invalid method name invocation2 := onepassword.Invocation{ClientID: uint64(validClientID), MethodName: invalidMethodName, SerializedParams: validParams} @@ -98,5 +98,5 @@ func TestInvalidInvoke(t *testing.T) { invocation3 := onepassword.Invocation{ClientID: uint64(validClientID), MethodName: validMethodName, SerializedParams: invalidParams} _, err3 := core.Invoke(invocation3) - assert.Equal(t, "wrong method", err3.Error()) + assert.Equal(t, "secret reference is not prefixed with \"op://\"", err3.Error()) } From 6453eca4253dbda2fd3aca8011eb07ee3e4c7f45 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Tue, 23 Jan 2024 10:26:34 -0500 Subject: [PATCH 14/16] tidying up small details --- client_test.go | 6 ++++-- integration_tests/integration_test.go | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client_test.go b/client_test.go index d26d690..314806a 100644 --- a/client_test.go +++ b/client_test.go @@ -80,6 +80,8 @@ func TestInvalidIntegrationVersionCharacters(t *testing.T) { } type TestCore struct { + id uint64 + clientExists map[uint64]bool } func (c TestCore) InitClient(config ClientConfig) (*uint64, error) { @@ -94,6 +96,6 @@ func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { func (c TestCore) ReleaseClient(clientID uint64) {} -func TestGarbageCollectorReleasesClient(t *testing.T) { - +func NewTestCore() *TestCore { + return &TestCore{clientExists: make(map[uint64]bool)} } diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index bd69d31..94ba33c 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -64,8 +64,6 @@ func TestInvalidInvoke(t *testing.T) { config.IntegrationName = "name" config.IntegrationVersion = "version" - value, _ := core.InitClient(config) - client, err := onepassword.NewClient(context.TODO(), onepassword.WithServiceAccountToken(token), onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion), @@ -75,10 +73,10 @@ func TestInvalidInvoke(t *testing.T) { secret, err := client.Secrets.Resolve("op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password") require.NoError(t, err) - validClientID := *value + validClientID := 0 validMethodName := "Resolve" validParams := *secret - invalidClientID := -1 + invalidClientID := 1 invalidMethodName := "" invalidParams := "" From 2ba76c1c007a3d694089c6d01457c03afb7bf431 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Tue, 23 Jan 2024 11:37:24 -0500 Subject: [PATCH 15/16] updated test core logic --- client_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client_test.go b/client_test.go index 314806a..bec5594 100644 --- a/client_test.go +++ b/client_test.go @@ -80,8 +80,6 @@ func TestInvalidIntegrationVersionCharacters(t *testing.T) { } type TestCore struct { - id uint64 - clientExists map[uint64]bool } func (c TestCore) InitClient(config ClientConfig) (*uint64, error) { @@ -95,7 +93,3 @@ func (c TestCore) Invoke(invokeConfig Invocation) (*string, error) { } func (c TestCore) ReleaseClient(clientID uint64) {} - -func NewTestCore() *TestCore { - return &TestCore{clientExists: make(map[uint64]bool)} -} From 70bba419f4a0874bcecd8d7cde1c00c0501c3ce1 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Tue, 23 Jan 2024 11:48:21 -0500 Subject: [PATCH 16/16] fixed invalid invoke --- integration_tests/integration_test.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/integration_tests/integration_test.go b/integration_tests/integration_test.go index 94ba33c..7f5723b 100644 --- a/integration_tests/integration_test.go +++ b/integration_tests/integration_test.go @@ -64,18 +64,12 @@ func TestInvalidInvoke(t *testing.T) { config.IntegrationName = "name" config.IntegrationVersion = "version" - client, err := onepassword.NewClient(context.TODO(), - onepassword.WithServiceAccountToken(token), - onepassword.WithIntegrationInfo("Integration_Test_Go_SDK", onepassword.DefaultIntegrationVersion), - ) - require.NoError(t, err) - - secret, err := client.Secrets.Resolve("op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password") + _, err := core.InitClient(config) require.NoError(t, err) validClientID := 0 validMethodName := "Resolve" - validParams := *secret + validParams := "op://tfctuk7dxnrwjwqqhwatuhy3gi/dqtyg7dswx5kvpcxwv32psdbse/password" invalidClientID := 1 invalidMethodName := "" invalidParams := ""