Files
threshold/internal/target/tcp/target_test.go
T
Timothy Messier c9b99306e1 refact(target): Add NewFunc to registry
This adds a new requirement onto subtypes to register a NewFunc.
Previously the subtypes where implementing this function anyway, but the
target package was not including them in the registry. This resulted in
packages that use the target package needing to import the subtypes
directly, which we want to avoid.

This refactor will require the subtypes to register their NewFunc which
can then be used by `target.New` so packages that need to create targets
can do so by only using the target package.

This also updates the tcp subpackage to register a NewFunc.
2021-12-03 10:19:29 -05:00

411 lines
11 KiB
Go

package tcp_test
import (
"context"
"testing"
"time"
"github.com/hashicorp/boundary/internal/db"
dbassert "github.com/hashicorp/boundary/internal/db/assert"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
func TestTarget_Create(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
wrapper := db.TestWrapper(t)
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
ctx := context.Background()
type args struct {
scopeId string
opt []target.Option
}
tests := []struct {
name string
args args
want target.Target
wantErr bool
wantIsErr errors.Code
create bool
wantCreateErr bool
}{
{
name: "empty-scopeId",
args: args{},
wantErr: true,
wantIsErr: errors.InvalidParameter,
},
{
name: "valid-proj-scope",
args: args{
scopeId: prj.PublicId,
opt: []target.Option{target.WithName("valid-proj-scope")},
},
want: func() target.Target {
t, _ := target.New(
ctx,
tcp.Subtype,
prj.PublicId,
target.WithName("valid-proj-scope"),
target.WithSessionMaxSeconds(uint32((8 * time.Hour).Seconds())),
target.WithSessionConnectionLimit(1),
)
return t
}(),
create: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := target.New(ctx, tcp.Subtype, tt.args.scopeId, tt.args.opt...)
if tt.wantErr {
require.Error(err)
assert.True(errors.Match(errors.T(tt.wantIsErr), err))
return
}
require.NoError(err)
assert.Equal(tt.want, got)
if tt.create {
id, err := db.NewPublicId(tcp.TargetPrefix)
require.NoError(err)
got.SetPublicId(ctx, id)
err = db.New(conn).Create(ctx, got)
if tt.wantCreateErr {
assert.Error(err)
return
}
assert.NoError(err)
}
})
}
}
func TestTarget_Delete(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
_, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
ctx := context.Background()
tests := []struct {
name string
target target.Target
wantRowsDeleted int
wantErr bool
wantErrMsg string
}{
{
name: "valid",
target: tcp.TestTarget(ctx, t, conn, proj.PublicId, tcp.TestTargetName(t, proj.PublicId)),
wantErr: false,
wantRowsDeleted: 1,
},
{
name: "bad-id",
target: func() target.Target {
tar, _ := target.New(ctx, tcp.Subtype, proj.PublicId)
id, err := db.NewPublicId(tcp.TargetPrefix)
require.NoError(t, err)
tar.SetPublicId(ctx, id)
tar.SetName(tcp.TestTargetName(t, proj.PublicId))
return tar
}(),
wantErr: false,
wantRowsDeleted: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
deleteTarget := tcp.NewTestTarget("")
deleteTarget.SetPublicId(ctx, tt.target.GetPublicId())
deletedRows, err := rw.Delete(context.Background(), deleteTarget)
if tt.wantErr {
require.Error(err)
return
}
require.NoError(err)
if tt.wantRowsDeleted == 0 {
assert.Equal(tt.wantRowsDeleted, deletedRows)
return
}
assert.Equal(tt.wantRowsDeleted, deletedRows)
foundTarget := tcp.NewTestTarget("")
foundTarget.SetPublicId(ctx, tt.target.GetPublicId())
err = rw.LookupById(context.Background(), foundTarget)
require.Error(err)
assert.True(errors.IsNotFoundError(err))
})
}
}
func TestTarget_Update(t *testing.T) {
t.Parallel()
id := tcp.TestId(t)
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
_, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
type args struct {
name string
description string
fieldMaskPaths []string
nullPaths []string
ScopeId string
}
tests := []struct {
name string
args args
wantRowsUpdate int
wantErr bool
wantErrMsg string
wantDup bool
}{
{
name: "valid",
args: args{
name: "valid" + id,
fieldMaskPaths: []string{"Name"},
ScopeId: proj.PublicId,
},
wantErr: false,
wantRowsUpdate: 1,
},
{
name: "proj-scope-id-not-in-mask",
args: args{
name: "proj-scope-id" + id,
fieldMaskPaths: []string{"Name"},
ScopeId: proj.PublicId,
},
wantErr: false,
wantRowsUpdate: 1,
},
{
name: "empty-scope-id",
args: args{
name: "empty-scope-id" + id,
fieldMaskPaths: []string{"Name"},
ScopeId: "",
},
wantErr: false,
wantRowsUpdate: 1,
},
{
name: "dup-name",
args: args{
name: "dup-name" + id,
fieldMaskPaths: []string{"Name"},
ScopeId: proj.PublicId,
},
wantErr: true,
wantDup: true,
wantErrMsg: `db.Update: duplicate key value violates unique constraint "target_tcp_scope_id_name_key": unique constraint violation: integrity violation: error #1002`,
},
{
name: "set description null",
args: args{
name: "set description null" + id,
fieldMaskPaths: []string{"Name"},
nullPaths: []string{"Description"},
ScopeId: proj.PublicId,
},
wantErr: false,
wantRowsUpdate: 1,
},
{
name: "set name null",
args: args{
description: "set description null" + id,
fieldMaskPaths: []string{"Description"},
nullPaths: []string{"Name"},
ScopeId: proj.PublicId,
},
wantErr: true,
wantErrMsg: `db.Update: name must not be empty: not null constraint violated: integrity violation: error #1001`,
},
{
name: "set description null",
args: args{
name: "set name null" + id,
fieldMaskPaths: []string{"Name"},
nullPaths: []string{"Description"},
ScopeId: proj.PublicId,
},
wantErr: false,
wantRowsUpdate: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
ctx := context.Background()
if tt.wantDup {
target := tcp.TestTarget(ctx, t, conn, proj.PublicId, tcp.TestTargetName(t, proj.PublicId))
target.SetName(tt.args.name)
_, err := rw.Update(ctx, target, tt.args.fieldMaskPaths, tt.args.nullPaths)
require.NoError(err)
}
id := tcp.TestId(t)
tar := tcp.TestTarget(ctx, t, conn, proj.PublicId, id, target.WithDescription(id))
updateTarget := tcp.NewTestTarget(tt.args.ScopeId)
updateTarget.SetPublicId(ctx, tar.GetPublicId())
updateTarget.SetName(tt.args.name)
updateTarget.SetDescription(tt.args.description)
updatedRows, err := rw.Update(ctx, updateTarget, tt.args.fieldMaskPaths, tt.args.nullPaths)
if tt.wantErr {
require.Error(err)
assert.Equal(0, updatedRows)
assert.Equal(tt.wantErrMsg, err.Error())
err = db.TestVerifyOplog(t, rw, tar.GetPublicId(), db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second))
require.Error(err)
assert.Contains(err.Error(), "record not found")
return
}
require.NoError(err)
assert.Equal(tt.wantRowsUpdate, updatedRows)
assert.NotEqual(tar.GetUpdateTime(), updateTarget.GetUpdateTime())
foundTarget := tcp.NewTestTarget(tt.args.ScopeId)
foundTarget.SetPublicId(ctx, tar.GetPublicId())
err = rw.LookupByPublicId(ctx, foundTarget)
require.NoError(err)
assert.True(proto.Equal(updateTarget.(*tcp.Target).Target, foundTarget.(*tcp.Target).Target))
if len(tt.args.nullPaths) != 0 {
underlyingDB, err := conn.SqlDB(ctx)
require.NoError(err)
dbassert := dbassert.New(t, underlyingDB)
for _, f := range tt.args.nullPaths {
ft := foundTarget.(*tcp.Target)
dbassert.IsNull(&ft, f)
}
}
})
}
t.Run("update dup names in diff scopes", func(t *testing.T) {
ctx := context.Background()
assert, require := assert.New(t), require.New(t)
id := tcp.TestId(t)
_, proj2 := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
_ = tcp.TestTarget(ctx, t, conn, proj2.PublicId, id, target.WithDescription(id))
projTarget := tcp.TestTarget(ctx, t, conn, proj.PublicId, id)
projTarget.SetName(id)
updatedRows, err := rw.Update(ctx, projTarget, []string{"Name"}, nil)
require.NoError(err)
assert.Equal(1, updatedRows)
foundTarget, _ := target.New(ctx, tcp.Subtype, proj2.PublicId)
foundTarget.SetPublicId(ctx, projTarget.GetPublicId())
err = rw.LookupByPublicId(ctx, foundTarget)
require.NoError(err)
assert.Equal(id, projTarget.GetName())
})
}
func TestTarget_Clone(t *testing.T) {
t.Parallel()
ctx := context.Background()
conn, _ := db.TestSetup(t, "postgres")
wrapper := db.TestWrapper(t)
t.Run("valid", func(t *testing.T) {
assert := assert.New(t)
_, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
tar := tcp.TestTarget(ctx, t, conn, proj.PublicId, tcp.TestTargetName(t, proj.PublicId))
cp := tar.Clone()
assert.True(proto.Equal(cp.(*tcp.Target).Target, tar.(*tcp.Target).Target))
})
t.Run("not-equal", func(t *testing.T) {
assert := assert.New(t)
_, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
_, proj2 := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
target1 := tcp.TestTarget(ctx, t, conn, proj.PublicId, tcp.TestTargetName(t, proj.PublicId))
target2 := tcp.TestTarget(ctx, t, conn, proj2.PublicId, tcp.TestTargetName(t, proj2.PublicId))
cp := target1.Clone()
assert.True(!proto.Equal(cp.(*tcp.Target).Target, target2.(*tcp.Target).Target))
})
}
func TestTable_SetTableName(t *testing.T) {
t.Parallel()
defaultTableName := tcp.DefaultTableName
ctx := context.Background()
tests := []struct {
name string
setNameTo string
want string
}{
{
name: "new-name",
setNameTo: "new-name",
want: "new-name",
},
{
name: "reset to default",
setNameTo: "",
want: defaultTableName,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
def, _ := target.New(ctx, tcp.Subtype, "testScope")
require.Equal(defaultTableName, def.(*tcp.Target).TableName())
ss, _ := target.New(ctx, tcp.Subtype, "testScope")
s := ss.(*tcp.Target)
s.SetTableName(tt.setNameTo)
assert.Equal(tt.want, s.TableName())
})
}
}
func TestTarget_oplog(t *testing.T) {
ctx := context.Background()
id := tcp.TestId(t)
tests := []struct {
name string
target target.Target
op oplog.OpType
want oplog.Metadata
}{
{
name: "simple",
target: func() target.Target {
tar, _ := target.New(ctx, tcp.Subtype, id)
if err := tar.SetPublicId(ctx, id); err != nil {
t.Fatalf("failed to set public id: %s", err)
}
return tar
}(),
op: oplog.OpType_OP_TYPE_CREATE,
want: oplog.Metadata{
"resource-public-id": []string{id},
"resource-type": []string{"tcp target"},
"op-type": []string{oplog.OpType_OP_TYPE_CREATE.String()},
"scope-id": []string{id},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
got := tt.target.Oplog(tt.op)
assert.Equal(got, tt.want)
})
}
}