Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb2892c3

Browse files
authored
test: Increase test coverage on auditable resources (#7038)
* test: Increase test coverage on auditable resourcesWhen adding a new audit resource, we also need to add it to thefunction switch statements. This is a likely mistake, now a unittest will check this for you
1 parent24d8644 commitb2892c3

File tree

6 files changed

+114
-5
lines changed

6 files changed

+114
-5
lines changed

‎coderd/audit/request.go‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ func ResourceTarget[T Auditable](tgt T) string {
7878
return""
7979
case database.License:
8080
returnstrconv.Itoa(int(typed.ID))
81+
case database.WorkspaceProxy:
82+
returntyped.Name
8183
default:
8284
panic(fmt.Sprintf("unknown resource %T",tgt))
8385
}
@@ -103,13 +105,15 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
103105
returntyped.UserID
104106
case database.License:
105107
returntyped.UUID
108+
case database.WorkspaceProxy:
109+
returntyped.ID
106110
default:
107111
panic(fmt.Sprintf("unknown resource %T",tgt))
108112
}
109113
}
110114

111115
funcResourceType[TAuditable](tgtT) database.ResourceType {
112-
switchany(tgt).(type) {
116+
switchtyped:=any(tgt).(type) {
113117
case database.Template:
114118
returndatabase.ResourceTypeTemplate
115119
case database.TemplateVersion:
@@ -128,8 +132,10 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
128132
returndatabase.ResourceTypeApiKey
129133
case database.License:
130134
returndatabase.ResourceTypeLicense
135+
case database.WorkspaceProxy:
136+
returndatabase.ResourceTypeWorkspaceProxy
131137
default:
132-
panic(fmt.Sprintf("unknown resource %T",tgt))
138+
panic(fmt.Sprintf("unknown resource %T",typed))
133139
}
134140
}
135141

‎coderd/database/dump.sql‎

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- It's not possible to drop enum values from enum types, so the UP has "IF NOT
2+
-- EXISTS".
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTERTYPE resource_type ADD VALUE IF NOT EXISTS'workspace_proxy';

‎coderd/database/models.go‎

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎enterprise/audit/table_internal_test.go‎

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
package audit
22

33
import (
4+
"fmt"
45
"go/types"
6+
"strings"
57
"testing"
68

79
"github.com/stretchr/testify/assert"
810
"github.com/stretchr/testify/require"
911
"golang.org/x/tools/go/packages"
12+
13+
"github.com/coder/coder/coderd/audit"
14+
"github.com/coder/coder/coderd/database"
15+
"github.com/coder/coder/coderd/util/slice"
1016
)
1117

1218
// TestAuditableResources ensures that all auditable resources are included in
1319
// the Auditable interface and vice versa.
20+
//
21+
//nolint:tparallel
1422
funcTestAuditableResources(t*testing.T) {
1523
t.Parallel()
1624

1725
pkgs,err:=packages.Load(&packages.Config{
18-
Mode:packages.NeedTypes,
26+
Mode:packages.NeedTypes|packages.NeedDeps,
1927
},"../../coderd/audit")
2028
require.NoError(t,err)
2129

@@ -37,13 +45,15 @@ func TestAuditableResources(t *testing.T) {
3745
require.True(t,ok,"expected Auditable to be a union")
3846

3947
found:=make(map[string]bool)
48+
expectedList:=make([]string,0)
4049
// Now we check we have all the resources in the AuditableResources
4150
fori:=0;i<unionType.Len();i++ {
4251
// All types come across like 'github.com/coder/coder/coderd/database.<type>'
4352
typeName:=unionType.Term(i).Type().String()
4453
_,ok:=AuditableResources[typeName]
4554
assert.True(t,ok,"missing resource %q from AuditableResources",typeName)
4655
found[typeName]=true
56+
expectedList=append(expectedList,typeName)
4757
}
4858

4959
// Also check that all resources in the table are in the union. We could
@@ -52,4 +62,90 @@ func TestAuditableResources(t *testing.T) {
5262
_,ok:=found[name]
5363
assert.True(t,ok,"extra resource %q found in AuditableResources",name)
5464
}
65+
66+
// Various functions that have switch statements to include all Auditable
67+
// resources. Make sure we have all types supported.
68+
// nolint:paralleltest
69+
t.Run("ResourceID",func(t*testing.T) {
70+
// The function being tested, provided here to make it easier to find
71+
_=audit.ResourceID[database.APIKey]
72+
testAuditFunctionWithSwitch(t,auditPkg,"ResourceID",expectedList)
73+
})
74+
75+
// nolint:paralleltest
76+
t.Run("ResourceType",func(t*testing.T) {
77+
// The function being tested, provided here to make it easier to find
78+
_=audit.ResourceType[database.APIKey]
79+
testAuditFunctionWithSwitch(t,auditPkg,"ResourceType",expectedList)
80+
})
81+
82+
// nolint:paralleltest
83+
t.Run("ResourceTarget",func(t*testing.T) {
84+
// The function being tested, provided here to make it easier to find
85+
_=audit.ResourceTarget[database.APIKey]
86+
testAuditFunctionWithSwitch(t,auditPkg,"ResourceTarget",expectedList)
87+
})
88+
}
89+
90+
// testAuditFunctionWithSwitch is a helper function to test that a function has
91+
// a typed switch statement that includes all the types in expectedTypes.
92+
functestAuditFunctionWithSwitch(t*testing.T,pkg*packages.Package,funcNamestring,expectedTypes []string) {
93+
t.Helper()
94+
95+
f,ok:=pkg.Types.Scope().Lookup(funcName).(*types.Func)
96+
require.True(t,ok,fmt.Sprintf("expected %s to be a function",funcName))
97+
switchCases:=findSwitchTypes(f)
98+
for_,expected:=rangeexpectedTypes {
99+
if!slice.Contains(switchCases,expected) {
100+
t.Errorf("%s switch statement is missing type %q. Include it in the switch case block",funcName,expected)
101+
}
102+
}
103+
for_,sc:=rangeswitchCases {
104+
if!slice.Contains(expectedTypes,sc) {
105+
t.Errorf("%s switch statement has unexpected type %q. Remove it from the switch case block",funcName,sc)
106+
}
107+
}
108+
}
109+
110+
// findSwitchTypes is a helper function to find all types a switch statement in
111+
// the function body of f has.
112+
funcfindSwitchTypes(f*types.Func) []string {
113+
caseTypes:=make([]string,0)
114+
switches:=returnSwitchBlocks(f.Scope())
115+
for_,sc:=rangeswitches {
116+
scTypes:=findCaseTypes(sc)
117+
caseTypes=append(caseTypes,scTypes...)
118+
}
119+
returncaseTypes
120+
}
121+
122+
funcreturnSwitchBlocks(sc*types.Scope) []*types.Scope {
123+
switches:=make([]*types.Scope,0)
124+
fori:=0;i<sc.NumChildren();i++ {
125+
child:=sc.Child(i)
126+
cStr:=child.String()
127+
// This is the easiest way to tell if it is a switch statement.
128+
ifstrings.Contains(cStr,"type switch scope") {
129+
switches=append(switches,child)
130+
}
131+
}
132+
returnswitches
133+
}
134+
135+
// findCaseTypes returns all case types in a typed switch statement. Excluding
136+
// the "Default:" case.
137+
funcfindCaseTypes(sc*types.Scope) []string {
138+
caseTypes:=make([]string,0)
139+
fori:=0;i<sc.NumChildren();i++ {
140+
child:=sc.Child(i)
141+
for_,name:=rangechild.Names() {
142+
obj:=child.Lookup(name).Type()
143+
typeName:=obj.String()
144+
// Ignore the "Default:" case
145+
iftypeName!="any" {
146+
caseTypes=append(caseTypes,typeName)
147+
}
148+
}
149+
}
150+
returncaseTypes
55151
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp