mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
Joins in fields like `username`, `avatar_url`, `organization_name`, `template_name` to `workspaces` via a **view**. The view must be maintained moving forward, but this prevents needing to add RBAC permissions to fetch related workspace fields.
103 lines
3.6 KiB
Go
103 lines
3.6 KiB
Go
package gentest_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
// TestAuditDBEnumsCovered ensures that all enums in the database are covered by the codersdk enums
|
|
// for audit log strings.
|
|
func TestAuditDBEnumsCovered(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dbTypes := database.AllResourceTypeValues()
|
|
for _, ty := range dbTypes {
|
|
str := codersdk.ResourceType(ty).FriendlyString()
|
|
require.NotEqualf(t, "unknown", str, "ResourceType %q not covered by codersdk.ResourceType", ty)
|
|
}
|
|
}
|
|
|
|
// TestViewSubsetTemplate ensures TemplateTable is a subset of Template
|
|
func TestViewSubsetTemplate(t *testing.T) {
|
|
t.Parallel()
|
|
table := reflect.TypeOf(database.TemplateTable{})
|
|
joined := reflect.TypeOf(database.Template{})
|
|
|
|
tableFields := allFields(table)
|
|
joinedFields := allFields(joined)
|
|
if !assert.Subset(t, fieldNames(joinedFields), fieldNames(tableFields), "table is not subset") {
|
|
t.Log("Some fields were added to the Template Table without updating the 'template_with_names' view.")
|
|
t.Log("See migration 000138_join_users.up.sql to create the view.")
|
|
}
|
|
}
|
|
|
|
// TestViewSubsetTemplateVersion ensures TemplateVersionTable is a subset TemplateVersion
|
|
func TestViewSubsetTemplateVersion(t *testing.T) {
|
|
t.Parallel()
|
|
table := reflect.TypeOf(database.TemplateVersionTable{})
|
|
joined := reflect.TypeOf(database.TemplateVersion{})
|
|
|
|
tableFields := allFields(table)
|
|
joinedFields := allFields(joined)
|
|
if !assert.Subset(t, fieldNames(joinedFields), fieldNames(tableFields), "table is not subset") {
|
|
t.Log("Some fields were added to the TemplateVersion Table without updating the 'template_version_with_user' view.")
|
|
t.Log("See migration 000141_join_users_build_version.up.sql to create the view.")
|
|
}
|
|
}
|
|
|
|
// TestViewSubsetWorkspaceBuild ensures WorkspaceBuildTable is a subset of WorkspaceBuild
|
|
func TestViewSubsetWorkspaceBuild(t *testing.T) {
|
|
t.Parallel()
|
|
table := reflect.TypeOf(database.WorkspaceBuildTable{})
|
|
joined := reflect.TypeOf(database.WorkspaceBuild{})
|
|
|
|
tableFields := allFields(table)
|
|
joinedFields := allFields(joined)
|
|
if !assert.Subset(t, fieldNames(joinedFields), fieldNames(tableFields), "table is not subset") {
|
|
t.Log("Some fields were added to the WorkspaceBuild Table without updating the 'workspace_build_with_user' view.")
|
|
t.Log("See migration 000141_join_users_build_version.up.sql to create the view.")
|
|
}
|
|
}
|
|
|
|
// TestViewSubsetWorkspace ensures WorkspaceTable is a subset of Workspace
|
|
func TestViewSubsetWorkspace(t *testing.T) {
|
|
t.Parallel()
|
|
table := reflect.TypeOf(database.WorkspaceTable{})
|
|
joined := reflect.TypeOf(database.Workspace{})
|
|
|
|
tableFields := allFields(table)
|
|
joinedFields := allFields(joined)
|
|
if !assert.Subset(t, fieldNames(joinedFields), fieldNames(tableFields), "table is not subset") {
|
|
t.Log("Some fields were added to the Workspace Table without updating the 'workspaces_expanded' view.")
|
|
t.Log("See migration 000262_workspace_with_names.up.sql to create the view.")
|
|
}
|
|
}
|
|
|
|
func fieldNames(fields []reflect.StructField) []string {
|
|
names := make([]string, len(fields))
|
|
for i, field := range fields {
|
|
names[i] = field.Name
|
|
}
|
|
return names
|
|
}
|
|
|
|
func allFields(rt reflect.Type) []reflect.StructField {
|
|
fields := make([]reflect.StructField, 0, rt.NumField())
|
|
for i := 0; i < rt.NumField(); i++ {
|
|
field := rt.Field(i)
|
|
if field.Anonymous && field.Type.Kind() == reflect.Struct {
|
|
// Recurse into anonymous struct fields.
|
|
fields = append(fields, allFields(field.Type)...)
|
|
continue
|
|
}
|
|
fields = append(fields, rt.Field(i))
|
|
}
|
|
return fields
|
|
}
|