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

Commitfeebf2b

Browse files
committed
add unit test to verify subset of fields
1 parent63ae42d commitfeebf2b

File tree

6 files changed

+160
-62
lines changed

6 files changed

+160
-62
lines changed

‎coderd/database/dbgen/dbgen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func WorkspaceAgentScriptTiming(t testing.TB, db database.Store, orig database.W
232232
returntiming
233233
}
234234

235-
funcWorkspace(t testing.TB,db database.Store,orig database.Workspace) database.Workspace {
235+
funcWorkspace(t testing.TB,db database.Store,orig database.WorkspaceTable) database.WorkspaceTable {
236236
t.Helper()
237237

238238
workspace,err:=db.InsertWorkspace(genCtx, database.InsertWorkspaceParams{

‎coderd/database/gentest/models_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ func TestViewSubsetWorkspaceBuild(t *testing.T) {
6565
}
6666
}
6767

68+
// TestViewSubsetWorkspace ensures WorkspaceTable is a subset of Workspace
69+
funcTestViewSubsetWorkspace(t*testing.T) {
70+
t.Parallel()
71+
table:=reflect.TypeOf(database.WorkspaceTable{})
72+
joined:=reflect.TypeOf(database.Workspace{})
73+
74+
tableFields:=allFields(table)
75+
joinedFields:=allFields(joined)
76+
if!assert.Subset(t,fieldNames(joinedFields),fieldNames(tableFields),"table is not subset") {
77+
t.Log("Some fields were added to the Workspace Table without updating the 'workspaces_expanded' view.")
78+
t.Log("See migration 000262_workspace_with_names.up.sql to create the view.")
79+
}
80+
}
81+
6882
funcfieldNames(fields []reflect.StructField) []string {
6983
names:=make([]string,len(fields))
7084
fori,field:=rangefields {

‎coderd/database/modelqueries_internal_test.go

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package database
22

33
import (
44
"fmt"
5-
"reflect"
65
"testing"
76

87
"github.com/stretchr/testify/require"
8+
9+
"github.com/coder/coder/v2/testutil"
910
)
1011

1112
funcTestIsAuthorizedQuery(t*testing.T) {
@@ -22,68 +23,12 @@ func TestWorkspaceTableConvert(t *testing.T) {
2223
t.Parallel()
2324

2425
varworkspaceWorkspace
25-
err:=populateStruct(&workspace)
26+
err:=testutil.PopulateStruct(&workspace,nil)
2627
require.NoError(t,err)
2728

28-
}
29-
30-
funcpopulateStruct(sinterface{})error {
31-
v:=reflect.ValueOf(s)
32-
ifv.Kind()!=reflect.Ptr||v.IsNil() {
33-
returnfmt.Errorf("s must be a non-nil pointer")
34-
}
35-
36-
v=v.Elem()
37-
ifv.Kind()!=reflect.Struct {
38-
returnfmt.Errorf("s must be a pointer to a struct")
39-
}
40-
41-
t:=v.Type()
42-
fori:=0;i<t.NumField();i++ {
43-
field:=t.Field(i)
44-
fieldName:=field.Name
45-
46-
fieldValue:=v.Field(i)
47-
if!fieldValue.CanSet() {
48-
continue// Skip if field is unexported
49-
}
29+
workspace.WorkspaceTable()
30+
require.JSONEq(t)
5031

51-
switchfieldValue.Kind() {
52-
casereflect.Struct:
53-
iferr:=populateStruct(fieldValue.Addr().Interface());err!=nil {
54-
returnfmt.Errorf("%s : %w",fieldName,err)
55-
}
56-
casereflect.String:
57-
fieldValue.SetString("foo")
58-
casereflect.Invalid:
59-
casereflect.Bool:
60-
casereflect.Int:
61-
casereflect.Int8:
62-
casereflect.Int16:
63-
casereflect.Int32:
64-
casereflect.Int64:
65-
casereflect.Uint:
66-
casereflect.Uint8:
67-
casereflect.Uint16:
68-
casereflect.Uint32:
69-
casereflect.Uint64:
70-
casereflect.Uintptr:
71-
casereflect.Float32:
72-
casereflect.Float64:
73-
casereflect.Complex64:
74-
casereflect.Complex128:
75-
casereflect.Array:
76-
casereflect.Chan:
77-
casereflect.Func:
78-
casereflect.Interface:
79-
casereflect.Map:
80-
casereflect.Pointer:
81-
casereflect.Slice:
82-
casereflect.UnsafePointer:
83-
default:
84-
returnfmt.Errorf("unsupported kind %s",fieldValue.Kind())
85-
}
86-
}
32+
fmt.Println(workspace)
8733

88-
returnnil
8934
}

‎testutil/reflect.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package testutil
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"time"
7+
)
8+
9+
typeRandomstruct {
10+
Stringfunc()string
11+
Boolfunc()bool
12+
Intfunc()int64
13+
Uintfunc()uint64
14+
Floatfunc()float64
15+
Complexfunc()complex128
16+
}
17+
18+
funcNewRandom()*Random {
19+
// Guaranteed to be random...
20+
return&Random{
21+
String:func()string {return"foo" },
22+
Bool:func()bool {returntrue },
23+
Int:func()int64 {return500 },
24+
Uint:func()uint64 {return126 },
25+
Float:func()float64 {return3.14 },
26+
Complex:func()complex128 {return6.24 },
27+
}
28+
}
29+
30+
// PopulateStruct does a best effort to populate a struct with random values.
31+
funcPopulateStruct(sinterface{},r*Random)error {
32+
ifr==nil {
33+
r=NewRandom()
34+
}
35+
36+
v:=reflect.ValueOf(s)
37+
ifv.Kind()!=reflect.Ptr||v.IsNil() {
38+
returnfmt.Errorf("s must be a non-nil pointer")
39+
}
40+
41+
v=v.Elem()
42+
ifv.Kind()!=reflect.Struct {
43+
returnfmt.Errorf("s must be a pointer to a struct")
44+
}
45+
46+
t:=v.Type()
47+
fori:=0;i<t.NumField();i++ {
48+
field:=t.Field(i)
49+
fieldName:=field.Name
50+
51+
fieldValue:=v.Field(i)
52+
if!fieldValue.CanSet() {
53+
continue// Skip if field is unexported
54+
}
55+
56+
nv,err:=populateValue(fieldValue,r)
57+
iferr!=nil {
58+
returnfmt.Errorf("%s : %w",fieldName,err)
59+
}
60+
v.Field(i).Set(nv)
61+
}
62+
63+
returnnil
64+
}
65+
66+
funcpopulateValue(v reflect.Value,r*Random) (reflect.Value,error) {
67+
varerrerror
68+
69+
// Handle some special cases
70+
switchv.Type() {
71+
casereflect.TypeOf(time.Time{}):
72+
v.Set(reflect.ValueOf(time.Date(2020,5,2,5,19,21,30,time.UTC)))
73+
returnv,nil
74+
}
75+
76+
switchv.Kind() {
77+
casereflect.Struct:
78+
iferr:=PopulateStruct(v.Addr().Interface(),r);err!=nil {
79+
returnv,err
80+
}
81+
casereflect.String:
82+
v.SetString(r.String())
83+
casereflect.Bool:
84+
v.SetBool(true)
85+
casereflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:
86+
v.SetInt(r.Int())
87+
casereflect.Uint,reflect.Uint8,reflect.Uint16,reflect.Uint32,reflect.Uint64:
88+
v.SetUint(r.Uint())
89+
casereflect.Float32,reflect.Float64:
90+
v.SetFloat(r.Float())
91+
casereflect.Complex64,reflect.Complex128:
92+
v.SetComplex(r.Complex())
93+
casereflect.Array:
94+
fori:=0;i<v.Len();i++ {
95+
nv,err:=populateValue(v.Index(i),r)
96+
iferr!=nil {
97+
returnv,fmt.Errorf("array index %d : %w",i,err)
98+
}
99+
v.Index(i).Set(nv)
100+
}
101+
casereflect.Map:
102+
m:=reflect.MakeMap(v.Type())
103+
104+
// Set a value in the map
105+
k:=reflect.New(v.Type().Key())
106+
kv:=reflect.New(v.Type().Elem())
107+
k,err=populateValue(k,r)
108+
iferr!=nil {
109+
returnv,fmt.Errorf("map key : %w",err)
110+
}
111+
kv,err=populateValue(kv,r)
112+
iferr!=nil {
113+
returnv,fmt.Errorf("map value : %w",err)
114+
}
115+
116+
m.SetMapIndex(k,kv)
117+
returnm,nil
118+
casereflect.Pointer:
119+
returnpopulateValue(v.Elem(),r)
120+
casereflect.Slice:
121+
s:=reflect.MakeSlice(v.Type(),2,2)
122+
sv,err:=populateValue(reflect.New(v.Type().Elem()),r)
123+
iferr!=nil {
124+
returnv,fmt.Errorf("slice value : %w",err)
125+
}
126+
127+
s.Index(0).Set(sv)
128+
s.Index(1).Set(sv)
129+
//reflect.AppendSlice(s, sv)
130+
131+
returns,nil
132+
casereflect.Uintptr,reflect.UnsafePointer,reflect.Chan,reflect.Func,reflect.Interface:
133+
// Unsupported
134+
returnv,fmt.Errorf("%s is not supported",v.Kind())
135+
default:
136+
returnv,fmt.Errorf("unsupported kind %s",v.Kind())
137+
}
138+
returnv,nil
139+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp