@@ -20,22 +20,86 @@ import (
20
20
"strings"
21
21
"sync"
22
22
"testing"
23
+ "time"
23
24
)
24
25
25
26
type mockRunner struct {
26
27
mu sync.Mutex
27
- t * testing.T
28
28
testCaseName string
29
29
commands []string
30
30
projectID string
31
+ configHelper string
31
32
}
32
33
33
- func newMockRunner (t * testing.T , projectID string ) * mockRunner {
34
- return & mockRunner {
35
- t : t ,
36
- projectID : projectID ,
34
+ const (
35
+ projectID = "my-project-id"
36
+ projectNum = 1234
37
+ // validConfig is what `gcloud config config-helper --format=json` spits out
38
+ validConfig = `{
39
+ "configuration": {
40
+ "active_configuration": "default",
41
+ "properties": {
42
+ "compute": {
43
+ "region": "us-central1",
44
+ "zone": "us-central1-f"
45
+ },
46
+ "core": {
47
+ "account": "bogus@not-a-domain.nowhere",
48
+ "disable_usage_reporting": "False",
49
+ "project": "my-project-id"
50
+ }
51
+ }
52
+ },
53
+ "credential": {
54
+ "access_token": "my-token",
55
+ "token_expiry": "2100-08-24T23:46:12Z"
56
+ },
57
+ "sentinels": {
58
+ "config_sentinel": "/home/someone/.config/gcloud/config_sentinel"
59
+ }
60
+ }
61
+ `
62
+ cfgNoToken = `{
63
+ "configuration": {
64
+ "properties": {
65
+ "core": {
66
+ "account": "bogus@not-a-domain.nowhere"
67
+ }
68
+ }
37
69
}
70
+ }`
71
+ cfgNoAcct = `{
72
+ "credential": {
73
+ "access_token": "my-token"
74
+ }
75
+ }`
76
+ cfgNoExpiration = `{
77
+ "configuration": {
78
+ "properties": {
79
+ "core": {
80
+ "account": "bogus@not-a-domain.nowhere"
81
+ }
82
+ }
83
+ },
84
+ "credential": {
85
+ "access_token": "my-token"
86
+ }
87
+ }`
88
+ cfgExpired = `{
89
+ "configuration": {
90
+ "properties": {
91
+ "core": {
92
+ "account": "bogus@not-a-domain.nowhere"
93
+ }
94
+ }
95
+ },
96
+ "credential": {
97
+ "access_token": "my-token",
98
+ "token_expiry": "1999-01-01T00:00:00Z"
99
+ }
38
100
}
101
+ `
102
+ )
39
103
40
104
// startsWith returns true iff arr startsWith parts.
41
105
func startsWith (arr []string , parts ... string ) bool {
@@ -57,10 +121,10 @@ func (r *mockRunner) Run(args []string, in io.Reader, out, err io.Writer, _ stri
57
121
58
122
if startsWith (args , "gcloud" , "config" , "list" ) {
59
123
fmt .Fprintln (out , r .projectID )
60
- } else if startsWith (args , "gcloud" , "projects" , "describe" ) {
61
- fmt .Fprintln (out , "1234" )
62
- } else if startsWith (args , "gcloud" , "config" , "config-helper" , "--format=value(credential.access_token) " ) {
63
- fmt .Fprintln (out , "my-token" )
124
+ } else if startsWith (args , "gcloud" , "projects" , "describe" ) && r . projectID == projectID {
125
+ fmt .Fprintln (out , projectNum )
126
+ } else if startsWith (args , "gcloud" , "config" , "config-helper" , "--format=json " ) {
127
+ fmt .Fprintln (out , r . configHelper )
64
128
}
65
129
66
130
return nil
@@ -79,45 +143,95 @@ func (r *mockRunner) Clean() error {
79
143
}
80
144
81
145
func TestAccessToken (t * testing.T ) {
82
- r := newMockRunner (t , "" )
146
+ // Happy case.
147
+ r := & mockRunner {configHelper : validConfig }
83
148
token , err := AccessToken (r )
84
149
if err != nil {
85
150
t .Errorf ("AccessToken failed: %v" , err )
86
151
}
87
- if token != "my-token" {
88
- t .Errorf ("AccessToken failed returning the token; got %s, want %s" , token , "my-token" )
152
+ if token .AccessToken != "my-token" {
153
+ t .Errorf ("AccessToken failed returning the token; got %q, want %q" , token .AccessToken , "my-token" )
154
+ }
155
+ if token .Email != "bogus@not-a-domain.nowhere" {
156
+ t .Errorf ("AccessToken failed returning the email; got %q, want %q" , token .Email , "bogus@not-a-domain.nowhere" )
89
157
}
90
158
got := strings .Join (r .commands , "\n " )
91
- want := "gcloud config config-helper --format=value(credential.access_token) "
159
+ want := "gcloud config config-helper --format=json "
92
160
if got != want {
93
161
t .Errorf ("Commands didn't match!\n ===Want:\n %s\n ===Got:\n %s" , want , got )
94
162
}
163
+
164
+ // We'll look for this error below...
165
+ _ , errParseTime := time .Parse (time .RFC3339 , "" )
166
+
167
+ // Unhappy cases
168
+ for _ , tc := range []struct {
169
+ desc string
170
+ json string
171
+ want error
172
+ }{{
173
+ desc : "empty json" ,
174
+ json : "{}" ,
175
+ want : errTokenNotFound ,
176
+ }, {
177
+ desc : "no token" ,
178
+ json : cfgNoToken ,
179
+ want : errTokenNotFound ,
180
+ }, {
181
+ desc : "no account" ,
182
+ json : cfgNoAcct ,
183
+ want : errAcctNotFound ,
184
+ }, {
185
+ desc : "no expiration" ,
186
+ json : cfgNoExpiration ,
187
+ want : errParseTime ,
188
+ }, {
189
+ desc : "expired" ,
190
+ json : cfgExpired ,
191
+ want : errTokenExpired ,
192
+ }} {
193
+ r .configHelper = tc .json
194
+ token , err = AccessToken (r )
195
+ if err .Error () != tc .want .Error () {
196
+ t .Errorf ("%s: got %v; want %v" , tc .desc , err , tc .want )
197
+ }
198
+ if token != nil {
199
+ t .Errorf ("%s: got unexpected token %v" , tc .desc , token )
200
+ }
201
+ }
95
202
}
96
203
97
204
func TestProjectInfo (t * testing.T ) {
98
- r := newMockRunner ( t , "my-project-id" )
205
+ r := & mockRunner { projectID : projectID }
99
206
projectInfo , err := ProjectInfo (r )
100
207
if err != nil {
101
208
t .Errorf ("ProjectInfo failed: %v" , err )
102
209
}
103
- if projectInfo .ProjectID != "my-project-id" {
104
- t .Errorf ("ProjectInfo failed returning the projectID; got %s, want %s" , projectInfo .ProjectID , "my-project-id" )
210
+ if projectInfo .ProjectID != projectID {
211
+ t .Errorf ("ProjectInfo failed returning the projectID; got %s, want %s" , projectInfo .ProjectID , projectID )
105
212
}
106
- if projectInfo .ProjectNum != 1234 {
107
- t .Errorf ("ProjectInfo failed returning the projectNum; got %d, want %d" , projectInfo .ProjectNum , 1234 )
213
+ if projectInfo .ProjectNum != projectNum {
214
+ t .Errorf ("ProjectInfo failed returning the projectNum; got %d, want %d" , projectInfo .ProjectNum , projectNum )
108
215
}
216
+
109
217
got := strings .Join (r .commands , "\n " )
110
218
want := strings .Join ([]string {`gcloud config list --format value(core.project)` ,
111
- `gcloud projects describe my-project-id --format value(projectNumber)` }, "\n " )
219
+ fmt . Sprintf ( `gcloud projects describe %s --format value(projectNumber)` , projectID ) }, "\n " )
112
220
if got != want {
113
221
t .Errorf ("Commands didn't match!\n ===Want:\n %s\n ===Got:\n %s" , want , got )
114
222
}
115
223
}
116
224
117
225
func TestProjectInfoError (t * testing.T ) {
118
- r := newMockRunner ( t , "" )
226
+ r := & mockRunner {}
119
227
_ , err := ProjectInfo (r )
120
228
if err == nil {
121
229
t .Errorf ("ProjectInfo should fail when no projectId set in gcloud" )
122
230
}
231
+
232
+ r .projectID = "some-other-project"
233
+ _ , err = ProjectInfo (r )
234
+ if err == nil {
235
+ t .Errorf ("ProjectInfo should fail when no projectNum available from gcloud" )
236
+ }
123
237
}
0 commit comments