mirror of
https://github.com/openziti/zrok.git
synced 2026-08-28 02:34:14 -05:00
452 lines
13 KiB
Go
452 lines
13 KiB
Go
package store
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestEphemeralEnvironment(t *testing.T) {
|
|
str, err := Open(&Config{Path: ":memory:", Type: "sqlite3"})
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, str)
|
|
|
|
trx, err := str.Begin()
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, trx)
|
|
|
|
envId, err := str.CreateEphemeralEnvironment(&Environment{
|
|
Description: "description",
|
|
Host: "host",
|
|
Address: "address",
|
|
ZId: "zId0",
|
|
}, trx)
|
|
assert.Nil(t, err)
|
|
|
|
env, err := str.GetEnvironment(envId, trx)
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, env)
|
|
assert.Nil(t, env.AccountId)
|
|
assert.False(t, env.Deleted)
|
|
}
|
|
|
|
func TestEnvironment(t *testing.T) {
|
|
str, err := Open(&Config{Path: ":memory:", Type: "sqlite3"})
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, str)
|
|
|
|
trx, err := str.Begin()
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, trx)
|
|
|
|
acctId, err := str.CreateAccount(&Account{
|
|
Email: "test@test.com",
|
|
Password: "password",
|
|
Token: "token",
|
|
}, trx)
|
|
assert.Nil(t, err)
|
|
|
|
envId, err := str.CreateEnvironment(acctId, &Environment{
|
|
Description: "description",
|
|
Host: "host",
|
|
Address: "address",
|
|
ZId: "zId0",
|
|
}, trx)
|
|
assert.Nil(t, err)
|
|
|
|
env, err := str.GetEnvironment(envId, trx)
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, env)
|
|
assert.NotNil(t, env.AccountId)
|
|
assert.Equal(t, acctId, *env.AccountId)
|
|
assert.False(t, env.Deleted)
|
|
}
|
|
|
|
func TestFindEnvironmentsForAccountWithFilter(t *testing.T) {
|
|
str, err := Open(&Config{Path: ":memory:", Type: "sqlite3"})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, str)
|
|
|
|
trx, err := str.Begin()
|
|
require.NoError(t, err)
|
|
require.NotNil(t, trx)
|
|
defer func() { _ = trx.Rollback() }()
|
|
|
|
// create test account
|
|
acctId, err := str.CreateAccount(&Account{
|
|
Email: "test@test.com",
|
|
Password: "password",
|
|
Token: "token",
|
|
Salt: "salt",
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
// create environments with varying properties
|
|
env1Id, err := str.CreateEnvironment(acctId, &Environment{
|
|
Description: "prod-server",
|
|
Host: "host1.example.com",
|
|
Address: "192.168.1.1",
|
|
ZId: "env1",
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
env2Id, err := str.CreateEnvironment(acctId, &Environment{
|
|
Description: "dev-server",
|
|
Host: "host2.example.com",
|
|
Address: "192.168.1.2",
|
|
ZId: "env2",
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
env3Id, err := str.CreateEnvironment(acctId, &Environment{
|
|
Description: "test-environment",
|
|
Host: "host3.example.com",
|
|
Address: "192.168.1.3",
|
|
ZId: "env3",
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
_, err = str.CreateEnvironment(acctId, &Environment{
|
|
Description: "staging-server",
|
|
Host: "host1.staging.com",
|
|
Address: "192.168.1.4",
|
|
ZId: "env4",
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
// create shares for environments
|
|
// env1: 1 share
|
|
_, err = str.CreateShare(env1Id, &Share{
|
|
ZId: "shr1",
|
|
Token: "token1",
|
|
ShareMode: "public",
|
|
BackendMode: "proxy",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
// env2: 3 shares
|
|
_, err = str.CreateShare(env2Id, &Share{
|
|
ZId: "shr2",
|
|
Token: "token2",
|
|
ShareMode: "public",
|
|
BackendMode: "proxy",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
_, err = str.CreateShare(env2Id, &Share{
|
|
ZId: "shr3",
|
|
Token: "token3",
|
|
ShareMode: "public",
|
|
BackendMode: "proxy",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
_, err = str.CreateShare(env2Id, &Share{
|
|
ZId: "shr4",
|
|
Token: "token4",
|
|
ShareMode: "public",
|
|
BackendMode: "proxy",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
// env3: 5 shares
|
|
for i := 0; i < 5; i++ {
|
|
_, err = str.CreateShare(env3Id, &Share{
|
|
ZId: "shr" + string(rune('5'+i)),
|
|
Token: "token" + string(rune('5'+i)),
|
|
ShareMode: "public",
|
|
BackendMode: "proxy",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// env4: 0 shares
|
|
|
|
// create frontends (accesses)
|
|
// env1: 2 frontends
|
|
_, err = str.CreateFrontend(env1Id, &Frontend{
|
|
Token: "frontend1",
|
|
ZId: "fzid1",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
_, err = str.CreateFrontend(env1Id, &Frontend{
|
|
Token: "frontend2",
|
|
ZId: "fzid2",
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
|
|
// env2: 5 frontends
|
|
for i := 0; i < 5; i++ {
|
|
_, err = str.CreateFrontend(env2Id, &Frontend{
|
|
Token: "frontend" + string(rune('3'+i)),
|
|
ZId: "fzid" + string(rune('3'+i)),
|
|
PermissionMode: OpenPermissionMode,
|
|
}, trx)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// env3 and env4: 0 frontends
|
|
|
|
t.Run("no filter returns all environments", func(t *testing.T) {
|
|
filter := &EnvironmentFilter{}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 4)
|
|
})
|
|
|
|
t.Run("description filter", func(t *testing.T) {
|
|
// should match "prod-server", "dev-server", "staging-server"
|
|
desc := "server"
|
|
filter := &EnvironmentFilter{Description: &desc}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 3)
|
|
|
|
// case insensitive
|
|
descUpper := "SERVER"
|
|
filter = &EnvironmentFilter{Description: &descUpper}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 3)
|
|
|
|
// specific match
|
|
descProd := "prod"
|
|
filter = &EnvironmentFilter{Description: &descProd}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env1", envs[0].ZId)
|
|
})
|
|
|
|
t.Run("host filter", func(t *testing.T) {
|
|
// should match "host1.example.com" and "host1.staging.com"
|
|
host := "host1"
|
|
filter := &EnvironmentFilter{Host: &host}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// case-insensitive
|
|
hostUpper := "HOST1"
|
|
filter = &EnvironmentFilter{Host: &hostUpper}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// specific domain
|
|
hostExample := "example.com"
|
|
filter = &EnvironmentFilter{Host: &hostExample}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 3)
|
|
})
|
|
|
|
t.Run("address filter", func(t *testing.T) {
|
|
addr := "192.168.1.1"
|
|
filter := &EnvironmentFilter{Address: &addr}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env1", envs[0].ZId)
|
|
})
|
|
|
|
t.Run("hasShares filter", func(t *testing.T) {
|
|
// hasShares = true (env1, env2, env3)
|
|
hasShares := true
|
|
filter := &EnvironmentFilter{HasShares: &hasShares}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 3)
|
|
|
|
// hasShares = false (env4)
|
|
hasShares = false
|
|
filter = &EnvironmentFilter{HasShares: &hasShares}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env4", envs[0].ZId)
|
|
assert.Equal(t, 0, envs[0].ShareCount)
|
|
})
|
|
|
|
t.Run("hasAccesses filter", func(t *testing.T) {
|
|
// hasAccesses = true (env1: 2, env2: 5)
|
|
hasAccesses := true
|
|
filter := &EnvironmentFilter{HasAccesses: &hasAccesses}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// hasAccesses = false (env3, env4)
|
|
hasAccesses = false
|
|
filter = &EnvironmentFilter{HasAccesses: &hasAccesses}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
})
|
|
|
|
t.Run("shareCount filter with operators", func(t *testing.T) {
|
|
// > 0 (env1: 1, env2: 3, env3: 5)
|
|
count := ">0"
|
|
filter := &EnvironmentFilter{ShareCount: &count}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 3)
|
|
|
|
// >= 3 (env2: 3, env3: 5)
|
|
count = ">=3"
|
|
filter = &EnvironmentFilter{ShareCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// = 1 (env1)
|
|
count = "=1"
|
|
filter = &EnvironmentFilter{ShareCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env1", envs[0].ZId)
|
|
assert.Equal(t, 1, envs[0].ShareCount)
|
|
|
|
// < 3 (env1: 1, env4: 0)
|
|
count = "<3"
|
|
filter = &EnvironmentFilter{ShareCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// <= 1 (env1: 1, env4: 0)
|
|
count = "<=1"
|
|
filter = &EnvironmentFilter{ShareCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
})
|
|
|
|
t.Run("accessCount filter with operators", func(t *testing.T) {
|
|
// > 0 (env1: 2, env2: 5)
|
|
count := ">0"
|
|
filter := &EnvironmentFilter{AccessCount: &count}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// >= 5 (env2: 5)
|
|
count = ">=5"
|
|
filter = &EnvironmentFilter{AccessCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env2", envs[0].ZId)
|
|
assert.Equal(t, 5, envs[0].AccessCount)
|
|
|
|
// = 2 (env1)
|
|
count = "=2"
|
|
filter = &EnvironmentFilter{AccessCount: &count}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env1", envs[0].ZId)
|
|
assert.Equal(t, 2, envs[0].AccessCount)
|
|
})
|
|
|
|
t.Run("date range filters", func(t *testing.T) {
|
|
t.Skip("skipping date range tests due to timestamp precision issues in test environment")
|
|
// TODO: implement proper date range testing with controlled timestamps
|
|
})
|
|
|
|
t.Run("combined filters", func(t *testing.T) {
|
|
// description contains "server" AND hasShares = true AND shareCount > 0
|
|
desc := "server"
|
|
hasShares := true
|
|
shareCount := ">0"
|
|
filter := &EnvironmentFilter{
|
|
Description: &desc,
|
|
HasShares: &hasShares,
|
|
ShareCount: &shareCount,
|
|
}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
// should match: prod-server (env1: 1 share), dev-server (env2: 3 shares), staging-server (env4: 0 shares - excluded)
|
|
assert.Len(t, envs, 2)
|
|
|
|
// host contains "host1" AND shareCount >= 1
|
|
host := "host1"
|
|
shareCount = ">=1"
|
|
filter = &EnvironmentFilter{
|
|
Host: &host,
|
|
ShareCount: &shareCount,
|
|
}
|
|
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
// should match: env1 (1 share), env4 has 0 shares (excluded)
|
|
assert.Len(t, envs, 1)
|
|
assert.Equal(t, "env1", envs[0].ZId)
|
|
})
|
|
|
|
t.Run("verify counts are correct", func(t *testing.T) {
|
|
filter := &EnvironmentFilter{}
|
|
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
|
|
require.NoError(t, err)
|
|
require.Len(t, envs, 4)
|
|
|
|
for _, env := range envs {
|
|
switch env.ZId {
|
|
case "env1":
|
|
assert.Equal(t, 1, env.ShareCount)
|
|
assert.Equal(t, 2, env.AccessCount)
|
|
case "env2":
|
|
assert.Equal(t, 3, env.ShareCount)
|
|
assert.Equal(t, 5, env.AccessCount)
|
|
case "env3":
|
|
assert.Equal(t, 5, env.ShareCount)
|
|
assert.Equal(t, 0, env.AccessCount)
|
|
case "env4":
|
|
assert.Equal(t, 0, env.ShareCount)
|
|
assert.Equal(t, 0, env.AccessCount)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestParseComparisonFilter(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
columnName string
|
|
expected string
|
|
expectError bool
|
|
}{
|
|
{"greater than", ">5", "count", "count > 5", false},
|
|
{"greater than or equal", ">=5", "count", "count >= 5", false},
|
|
{"equal", "=5", "count", "count = 5", false},
|
|
{"less than", "<5", "count", "count < 5", false},
|
|
{"less than or equal", "<=5", "count", "count <= 5", false},
|
|
{"no operator defaults to equal", "5", "count", "count = 5", false},
|
|
{"with spaces", " >= 10 ", "count", "count >= 10", false},
|
|
{"empty string", "", "count", "", true},
|
|
{"non-numeric value", ">abc", "count", "", true},
|
|
{"invalid operator", "~5", "count", "", true}, // no valid operator, can't parse as number
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, err := parseComparisonFilter(tt.input, tt.columnName)
|
|
if tt.expectError {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|