// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: BUSL-1.1

package iam

import (
	"context"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/hashicorp/boundary/internal/db"
	"github.com/hashicorp/boundary/internal/errors"
	"github.com/hashicorp/boundary/internal/iam/store"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/testing/protocmp"
)

func TestNewUserRole(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	orgRole := TestRole(t, conn, org.PublicId)
	projRole := TestRole(t, conn, proj.PublicId)
	user := TestUser(t, repo, org.PublicId)

	type args struct {
		roleId string
		userId string
		opt    []Option
	}
	tests := []struct {
		name      string
		args      args
		want      *UserRole
		wantErr   bool
		wantIsErr errors.Code
	}{
		{
			name: "valid-org",
			args: args{
				roleId: orgRole.PublicId,
				userId: user.PublicId,
			},
			want: func() *UserRole {
				r := allocUserRole()
				r.RoleId = orgRole.PublicId
				r.PrincipalId = user.PublicId
				return &r
			}(),
		},
		{
			name: "valid-proj",
			args: args{
				roleId: projRole.PublicId,
				userId: user.PublicId,
			},
			want: func() *UserRole {
				r := allocUserRole()
				r.RoleId = projRole.PublicId
				r.PrincipalId = user.PublicId
				return &r
			}(),
		},
		{
			name: "empty-role-id",
			args: args{
				roleId: "",
				userId: user.PublicId,
			},
			want:      nil,
			wantErr:   true,
			wantIsErr: errors.InvalidParameter,
		},
		{
			name: "empty-user-id",
			args: args{
				roleId: orgRole.PublicId,
				userId: "",
			},
			want:      nil,
			wantErr:   true,
			wantIsErr: errors.InvalidParameter,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			got, err := NewUserRole(ctx, tt.args.roleId, tt.args.userId, 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)
		})
	}
}

func TestUserRole_Create(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	org2, proj2 := TestScopes(t, repo)
	type args struct {
		role *UserRole
	}
	tests := []struct {
		name       string
		args       args
		wantDup    bool
		wantErr    bool
		wantErrMsg string
		wantIsErr  errors.Code
	}{
		{
			name: "valid-with-org",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, org.PublicId)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr: false,
		},
		{
			name: "valid-with-proj",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, proj.PublicId)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr: false,
		},
		{
			name: "cross-org",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, org2.PublicId)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
		},
		{
			name: "cross-proj",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, proj2.PublicId)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
		},
		{
			name: "bad-role-id",
			args: args{
				role: func() *UserRole {
					id := testId(t)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, id, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr:    true,
			wantErrMsg: "integrity violation: error #1003",
		},
		{
			name: "bad-user-id",
			args: args{
				role: func() *UserRole {
					id := testId(t)
					role := TestRole(t, conn, proj.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, id)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr:    true,
			wantErrMsg: "integrity violation: error #1003",
		},
		{
			name: "missing-role-id",
			args: args{
				role: func() *UserRole {
					principal := TestUser(t, repo, org.PublicId)
					return &UserRole{
						UserRole: &store.UserRole{
							RoleId:      "",
							PrincipalId: principal.PublicId,
						},
					}
				}(),
			},
			wantErr:    true,
			wantErrMsg: "iam.(UserRole).VetForWrite: missing role id: parameter violation: error #100",
			wantIsErr:  errors.InvalidParameter,
		},
		{
			name: "missing-user-id",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, proj.PublicId)
					return &UserRole{
						UserRole: &store.UserRole{
							RoleId:      role.PublicId,
							PrincipalId: "",
						},
					}
				}(),
			},
			wantErr:    true,
			wantErrMsg: "iam.(UserRole).VetForWrite: missing user id: parameter violation: error #100",
			wantIsErr:  errors.InvalidParameter,
		},
		{
			name: "dup-at-org",
			args: args{
				role: func() *UserRole {
					role := TestRole(t, conn, org.PublicId)
					principal := TestUser(t, repo, org.PublicId)
					principalRole, err := NewUserRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantDup:    true,
			wantErr:    true,
			wantErrMsg: `db.Create: duplicate key value violates unique constraint "iam_user_role_pkey": unique constraint violation`,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			w := db.New(conn)
			if tt.wantDup {
				r := tt.args.role.Clone().(*UserRole)
				err := w.Create(context.Background(), r)
				require.NoError(err)
			}
			r := tt.args.role.Clone().(*UserRole)
			err := w.Create(context.Background(), r)
			if tt.wantErr {
				require.Error(err)
				assert.Contains(err.Error(), tt.wantErrMsg)
				assert.True(errors.Match(errors.T(tt.wantIsErr), err))
				return
			}
			assert.NoError(err)

			found := allocUserRole()
			err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []any{r.RoleId, r.PrincipalId})
			require.NoError(err)
			assert.Empty(cmp.Diff(r, &found, protocmp.Transform()))
		})
	}
}

func TestUserRole_Update(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, _ := TestScopes(t, repo)
	rw := db.New(conn)

	t.Run("updates not allowed", func(t *testing.T) {
		assert, require := assert.New(t), require.New(t)
		r := TestRole(t, conn, org.PublicId)
		u := TestUser(t, repo, org.PublicId)
		u2 := TestUser(t, repo, org.PublicId)
		userRole := TestUserRole(t, conn, r.PublicId, u.PublicId)
		updateRole := userRole.Clone().(*UserRole)
		updateRole.PrincipalId = u2.PublicId
		updatedRows, err := rw.Update(context.Background(), updateRole, []string{"PrincipalId"}, nil)
		require.Error(err)
		assert.Equal(0, updatedRows)
	})
}

func TestUserRole_Delete(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	rw := db.New(conn)
	id := testId(t)
	org, _ := TestScopes(t, repo)
	u := TestUser(t, repo, org.PublicId)
	r := TestRole(t, conn, org.PublicId)

	tests := []struct {
		name            string
		role            *UserRole
		wantRowsDeleted int
		wantErr         bool
		wantErrMsg      string
	}{
		{
			name:            "valid",
			role:            TestUserRole(t, conn, r.PublicId, u.PublicId),
			wantErr:         false,
			wantRowsDeleted: 1,
		},
		{
			name:            "bad-id",
			role:            func() *UserRole { r := allocUserRole(); r.PrincipalId = id; r.RoleId = id; return &r }(),
			wantErr:         false,
			wantRowsDeleted: 0,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			deleteRole := allocUserRole()
			deleteRole.RoleId = tt.role.GetRoleId()
			deleteRole.PrincipalId = tt.role.GetPrincipalId()
			deletedRows, err := rw.Delete(context.Background(), &deleteRole)
			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)
			found := allocUserRole()
			err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []any{tt.role.GetRoleId(), tt.role.GetPrincipalId()})
			require.Error(err)
			assert.True(errors.IsNotFoundError(err))
		})
	}
}

func TestUserRole_Clone(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	user := TestUser(t, repo, org.PublicId)
	t.Run("valid", func(t *testing.T) {
		assert := assert.New(t)
		role := TestRole(t, conn, org.PublicId)
		userRole := TestUserRole(t, conn, role.PublicId, user.PublicId)
		cp := userRole.Clone()
		assert.True(proto.Equal(cp.(*UserRole).UserRole, userRole.UserRole))
	})
	t.Run("not-equal", func(t *testing.T) {
		assert := assert.New(t)
		role := TestRole(t, conn, org.PublicId)
		role2 := TestRole(t, conn, proj.PublicId)
		userRole := TestUserRole(t, conn, role.PublicId, user.PublicId)
		userRole2 := TestUserRole(t, conn, role2.PublicId, user.PublicId)
		cp := userRole.Clone()
		assert.True(!proto.Equal(cp.(*UserRole).UserRole, userRole2.UserRole))
	})
}

func TestNewGroupRole(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	orgRole := TestRole(t, conn, org.PublicId)
	projRole := TestRole(t, conn, proj.PublicId)
	group := TestGroup(t, conn, org.PublicId)

	type args struct {
		roleId  string
		groupId string
		opt     []Option
	}
	tests := []struct {
		name      string
		args      args
		want      *GroupRole
		wantErr   bool
		wantIsErr errors.Code
	}{
		{
			name: "valid-org",
			args: args{
				roleId:  orgRole.PublicId,
				groupId: group.PublicId,
			},
			want: func() *GroupRole {
				r := allocGroupRole()
				r.RoleId = orgRole.PublicId
				r.PrincipalId = group.PublicId
				return &r
			}(),
		},
		{
			name: "valid-proj",
			args: args{
				roleId:  projRole.PublicId,
				groupId: group.PublicId,
			},
			want: func() *GroupRole {
				r := allocGroupRole()
				r.RoleId = projRole.PublicId
				r.PrincipalId = group.PublicId
				return &r
			}(),
		},
		{
			name: "empty-role-id",
			args: args{
				roleId:  "",
				groupId: group.PublicId,
			},
			want:      nil,
			wantErr:   true,
			wantIsErr: errors.InvalidParameter,
		},
		{
			name: "empty-group-id",
			args: args{
				roleId:  orgRole.PublicId,
				groupId: "",
			},
			want:      nil,
			wantErr:   true,
			wantIsErr: errors.InvalidParameter,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			got, err := NewGroupRole(ctx, tt.args.roleId, tt.args.groupId, 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)
		})
	}
}

func TestGroupRole_Create(t *testing.T) {
	t.Parallel()
	ctx := context.Background()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	org2, proj2 := TestScopes(t, repo)
	type args struct {
		role *GroupRole
	}
	tests := []struct {
		name       string
		args       args
		wantDup    bool
		wantErr    bool
		wantErrMsg string
		wantIsErr  errors.Code
	}{
		{
			name: "valid-with-org",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, org.PublicId)
					principal := TestGroup(t, conn, org.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr: false,
		},
		{
			name: "valid-with-proj",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, proj.PublicId)
					principal := TestGroup(t, conn, proj.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr: false,
		},
		{
			name: "cross-org",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, org2.PublicId)
					principal := TestGroup(t, conn, org.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
		},
		{
			name: "cross-proj",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, proj2.PublicId)
					principal := TestGroup(t, conn, org.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
		},
		{
			name: "bad-role-id",
			args: args{
				role: func() *GroupRole {
					id := testId(t)
					principal := TestGroup(t, conn, org.PublicId)
					principalRole, err := NewGroupRole(ctx, id, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr:    true,
			wantErrMsg: "integrity violation: error #1003",
		},
		{
			name: "bad-user-id",
			args: args{
				role: func() *GroupRole {
					id := testId(t)
					role := TestRole(t, conn, proj.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, id)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantErr:    true,
			wantErrMsg: "integrity violation: error #1003",
		},
		{
			name: "missing-role-id",
			args: args{
				role: func() *GroupRole {
					principal := TestGroup(t, conn, org.PublicId)
					return &GroupRole{
						GroupRole: &store.GroupRole{
							RoleId:      "",
							PrincipalId: principal.PublicId,
						},
					}
				}(),
			},
			wantErr:    true,
			wantErrMsg: "parameter violation: error #100",
			wantIsErr:  errors.InvalidParameter,
		},
		{
			name: "missing-group-id",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, proj.PublicId)
					return &GroupRole{
						GroupRole: &store.GroupRole{
							RoleId:      role.PublicId,
							PrincipalId: "",
						},
					}
				}(),
			},
			wantErr:    true,
			wantErrMsg: "parameter violation: error #100",
			wantIsErr:  errors.InvalidParameter,
		},
		{
			name: "dup-at-org",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, org.PublicId)
					principal := TestGroup(t, conn, org.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantDup:    true,
			wantErr:    true,
			wantErrMsg: `unique constraint violation: integrity violation: error #1002`,
		},
		{
			name: "dup-at-proj",
			args: args{
				role: func() *GroupRole {
					role := TestRole(t, conn, proj.PublicId)
					principal := TestGroup(t, conn, proj.PublicId)
					principalRole, err := NewGroupRole(ctx, role.PublicId, principal.PublicId)
					require.NoError(t, err)
					return principalRole
				}(),
			},
			wantDup:    true,
			wantErr:    true,
			wantErrMsg: `unique constraint violation: integrity violation: error #1002`,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			w := db.New(conn)
			if tt.wantDup {
				r := tt.args.role.Clone().(*GroupRole)
				err := w.Create(context.Background(), r)
				require.NoError(err)
			}
			r := tt.args.role.Clone().(*GroupRole)
			err := w.Create(context.Background(), r)
			if tt.wantErr {
				require.Error(err)
				assert.Contains(err.Error(), tt.wantErrMsg)
				assert.True(errors.Match(errors.T(tt.wantIsErr), err))
				return
			}
			assert.NoError(err)

			found := allocGroupRole()
			err = w.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []any{r.RoleId, r.PrincipalId})
			require.NoError(err)
			assert.Empty(cmp.Diff(r, &found, protocmp.Transform()))
		})
	}
}

func TestGroupRole_Update(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, _ := TestScopes(t, repo)
	rw := db.New(conn)

	t.Run("updates not allowed", func(t *testing.T) {
		assert, require := assert.New(t), require.New(t)
		r := TestRole(t, conn, org.PublicId)
		g := TestGroup(t, conn, org.PublicId)
		g2 := TestGroup(t, conn, org.PublicId)
		groupRole := TestGroupRole(t, conn, r.PublicId, g.PublicId)
		updateRole := groupRole.Clone().(*GroupRole)
		updateRole.PrincipalId = g2.PublicId
		updatedRows, err := rw.Update(context.Background(), updateRole, []string{"PrincipalId"}, nil)
		require.Error(err)
		assert.Equal(0, updatedRows)
	})
}

func TestGroupRole_Delete(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	rw := db.New(conn)
	id := testId(t)
	org, _ := TestScopes(t, repo)
	g := TestGroup(t, conn, org.PublicId)
	r := TestRole(t, conn, org.PublicId)

	tests := []struct {
		name            string
		role            *GroupRole
		wantRowsDeleted int
		wantErr         bool
		wantErrMsg      string
	}{
		{
			name:            "valid",
			role:            TestGroupRole(t, conn, r.PublicId, g.PublicId),
			wantErr:         false,
			wantRowsDeleted: 1,
		},
		{
			name: "bad-id",
			role: func() *GroupRole {
				r := allocGroupRole()
				r.PrincipalId = id
				r.RoleId = id
				return &r
			}(),
			wantErr:         false,
			wantRowsDeleted: 0,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			deleteRole := allocGroupRole()
			deleteRole.RoleId = tt.role.GetRoleId()
			deleteRole.PrincipalId = tt.role.GetPrincipalId()
			deletedRows, err := rw.Delete(context.Background(), &deleteRole)
			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)
			found := allocGroupRole()
			err = rw.LookupWhere(context.Background(), &found, "role_id = ? and principal_id = ?", []any{tt.role.GetRoleId(), tt.role.GetPrincipalId()})
			require.Error(err)
			assert.True(errors.IsNotFoundError(err))
		})
	}
}

func TestGroupRole_Clone(t *testing.T) {
	t.Parallel()
	conn, _ := db.TestSetup(t, "postgres")
	wrapper := db.TestWrapper(t)
	repo := TestRepo(t, conn, wrapper)
	org, proj := TestScopes(t, repo)
	t.Run("valid", func(t *testing.T) {
		assert := assert.New(t)
		grp := TestGroup(t, conn, org.PublicId)
		role := TestRole(t, conn, org.PublicId)
		grpRole := TestGroupRole(t, conn, role.PublicId, grp.PublicId)
		cp := grpRole.Clone()
		assert.True(proto.Equal(cp.(*GroupRole).GroupRole, grpRole.GroupRole))
	})
	t.Run("not-equal", func(t *testing.T) {
		assert := assert.New(t)
		grp := TestGroup(t, conn, org.PublicId)
		grp2 := TestGroup(t, conn, proj.PublicId)
		role := TestRole(t, conn, org.PublicId)
		role2 := TestRole(t, conn, proj.PublicId)
		grpRole := TestGroupRole(t, conn, role.PublicId, grp.PublicId)
		grpRole2 := TestGroupRole(t, conn, role2.PublicId, grp2.PublicId)
		cp := grpRole.Clone()
		assert.True(!proto.Equal(cp.(*GroupRole).GroupRole, grpRole2.GroupRole))
	})
}

func TestPrincipalRole_SetTableName(t *testing.T) {
	defaultTableName := principalRoleViewDefaultTable
	tests := []struct {
		name        string
		initialName string
		setNameTo   string
		want        string
	}{
		{
			name:        "new-name",
			initialName: "",
			setNameTo:   "new-name",
			want:        "new-name",
		},
		{
			name:        "reset to default",
			initialName: "initial",
			setNameTo:   "",
			want:        defaultTableName,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			def := &PrincipalRole{
				PrincipalRoleView: &store.PrincipalRoleView{},
			}
			require.Equal(defaultTableName, def.TableName())
			s := &PrincipalRole{
				PrincipalRoleView: &store.PrincipalRoleView{},
				tableName:         tt.initialName,
			}
			s.SetTableName(tt.setNameTo)
			assert.Equal(tt.want, s.TableName())
		})
	}
}

func TestUserRole_SetTableName(t *testing.T) {
	defaultTableName := userRoleDefaultTable
	tests := []struct {
		name        string
		initialName string
		setNameTo   string
		want        string
	}{
		{
			name:        "new-name",
			initialName: "",
			setNameTo:   "new-name",
			want:        "new-name",
		},
		{
			name:        "reset to default",
			initialName: "initial",
			setNameTo:   "",
			want:        defaultTableName,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			def := allocUserRole()
			require.Equal(defaultTableName, def.TableName())
			s := &UserRole{
				UserRole:  &store.UserRole{},
				tableName: tt.initialName,
			}
			s.SetTableName(tt.setNameTo)
			assert.Equal(tt.want, s.TableName())
		})
	}
}

func TestGroupRole_SetTableName(t *testing.T) {
	defaultTableName := groupRoleDefaultTable
	tests := []struct {
		name        string
		initialName string
		setNameTo   string
		want        string
	}{
		{
			name:        "new-name",
			initialName: "",
			setNameTo:   "new-name",
			want:        "new-name",
		},
		{
			name:        "reset to default",
			initialName: "initial",
			setNameTo:   "",
			want:        defaultTableName,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			def := allocGroupRole()
			require.Equal(defaultTableName, def.TableName())
			s := &GroupRole{
				GroupRole: &store.GroupRole{},
				tableName: tt.initialName,
			}
			s.SetTableName(tt.setNameTo)
			assert.Equal(tt.want, s.TableName())
		})
	}
}

func TestManagedGroupRole_SetTableName(t *testing.T) {
	defaultTableName := managedGroupRoleDefaultTable
	tests := []struct {
		name        string
		initialName string
		setNameTo   string
		want        string
	}{
		{
			name:        "new-name",
			initialName: "",
			setNameTo:   "new-name",
			want:        "new-name",
		},
		{
			name:        "reset to default",
			initialName: "initial",
			setNameTo:   "",
			want:        defaultTableName,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert, require := assert.New(t), require.New(t)
			def := AllocManagedGroupRole()
			require.Equal(defaultTableName, def.TableName())
			s := &ManagedGroupRole{
				ManagedGroupRole: &store.ManagedGroupRole{},
				tableName:        tt.initialName,
			}
			s.SetTableName(tt.setNameTo)
			assert.Equal(tt.want, s.TableName())
		})
	}
}
