blob: e84b1f64d9c947e7f720a36251d99349176bb525 [file] [log] [blame]
Nicolas LaCasse156c60b2014-08-07 15:29:59 -07001package wspr
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "net/http"
8 "net/http/httptest"
9 "testing"
10 "time"
11
12 "veyron2/context"
13 "veyron2/ipc"
14 "veyron2/security"
15 "veyron2/vdl/vdlutil"
16)
17
18// BEGIN MOCK BLESSER SERVICE
19// TODO(nlacasse): Is there a better way to mock this?!
20type mockBlesserService struct {
21 id security.PrivateID
22 count int
23}
24
25func newMockBlesserService(id security.PrivateID) *mockBlesserService {
26 return &mockBlesserService{
27 id: id,
28 count: 0,
29 }
30}
31
32func (m *mockBlesserService) BlessUsingAccessToken(c context.T, accessToken string, co ...ipc.CallOpt) (vdlutil.Any, error) {
33 m.count = m.count + 1
34 name := fmt.Sprintf("mock-blessing-%v", m.count)
35 return m.id.Bless(m.id.PublicID(), name, 5*time.Minute, nil)
36}
37
38// This is never used. Only needed for mock.
39func (m *mockBlesserService) BlessUsingAuthorizationCode(c context.T, authCode, redirect string, co ...ipc.CallOpt) (vdlutil.Any, error) {
40 return m.id.PublicID(), nil
41}
42
43// This is never used. Only needed for mock.
44func (m *mockBlesserService) GetMethodTags(c context.T, s string, co ...ipc.CallOpt) ([]interface{}, error) {
45 return nil, nil
46}
47
48// This is never used. Only needed for mock.
49func (m *mockBlesserService) Signature(c context.T, co ...ipc.CallOpt) (ipc.ServiceSignature, error) {
50 return ipc.ServiceSignature{}, nil
51}
52
53// This is never used. Only needed for mock.
54func (m *mockBlesserService) UnresolveStep(c context.T, co ...ipc.CallOpt) ([]string, error) {
55 return []string{}, nil
56}
57
58// END MOCK BLESSER SERVICE
59
60func setup(t *testing.T) (*WSPR, func()) {
61 wspr := NewWSPR(0, "/mock/proxy", "/mock/identd")
62 providerId := wspr.rt.Identity()
63
64 wspr.blesserService = newMockBlesserService(providerId)
65 return wspr, func() {
66 wspr.Shutdown()
67 }
68}
69
70func TestHandleCreateAccount(t *testing.T) {
71 wspr, teardown := setup(t)
72 defer teardown()
73
74 method := "POST"
75 path := "/create-account"
76
77 // Add one account
78 data1 := createAccountInput{
79 AccessToken: "mock-access-token-1",
80 }
81 data1Json, err := json.Marshal(data1)
82 if err != nil {
83 t.Fatalf("json.Marshal(%v) failed: %v", data1, err)
84 }
85
86 data1JsonReader := bytes.NewReader(data1Json)
87 req, err := http.NewRequest(method, path, (data1JsonReader))
88 if err != nil {
89 t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, data1JsonReader, err)
90 }
91
92 resp1 := httptest.NewRecorder()
93 wspr.handleCreateAccount(resp1, req)
94 if resp1.Code != 200 {
95 t.Fatalf("Expected handleCreateAccount to return 200 OK, instead got %v", resp1)
96 }
97
98 // Verify that idManager has the new account
99 topLevelName := wspr.rt.Identity().PublicID().Names()[0]
100 expectedAccountName := topLevelName + "/mock-blessing-1"
Asim Shankar6bc64582014-08-27 12:51:42 -0700101 gotAccounts := wspr.idManager.AccountsMatching(security.BlessingPattern(expectedAccountName))
Nicolas LaCasse156c60b2014-08-07 15:29:59 -0700102 if len(gotAccounts) != 1 {
103 t.Fatalf("Expected to have 1 account with name %v, but got %v: %v", expectedAccountName, len(gotAccounts), gotAccounts)
104 }
105
106 // Add another account
107 data2 := createAccountInput{
108 AccessToken: "mock-access-token-2",
109 }
110 data2Json, err := json.Marshal(data2)
111 if err != nil {
112 t.Fatalf("json.Marshal(%v) failed: %v", data2, err)
113 }
114 data2JsonReader := bytes.NewReader(data2Json)
115 req, err = http.NewRequest(method, path, data2JsonReader)
116 if err != nil {
117 t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, data2JsonReader, err)
118 }
119
120 resp2 := httptest.NewRecorder()
121 wspr.handleCreateAccount(resp2, req)
122 if resp2.Code != 200 {
123 t.Fatalf("Expected handleCreateAccount to return 200 OK, instead got %v", resp2)
124 }
125
126 // Verify that idManager has both accounts
Asim Shankar9f6db082014-08-27 16:44:03 -0700127 gotAccounts = wspr.idManager.AccountsMatching(security.BlessingPattern(fmt.Sprintf("%s%s%v", topLevelName, security.ChainSeparator, security.AllPrincipals)))
Nicolas LaCasse156c60b2014-08-07 15:29:59 -0700128 if len(gotAccounts) != 2 {
129 t.Fatalf("Expected to have 2 accounts, but got %v: %v", len(gotAccounts), gotAccounts)
130 }
131}
132
133func TestHandleAssocAccount(t *testing.T) {
134 wspr, teardown := setup(t)
135 defer teardown()
136
137 // First create an accounts.
138 accountName := "mock-account"
139 identityName := "mock-id"
140 privateID, err := wspr.rt.NewIdentity(identityName)
141 if err != nil {
142 t.Fatalf("wspr.rt.NewIdentity(%v) failed: %v", identityName, err)
143 }
144 if err := wspr.idManager.AddAccount(accountName, privateID); err != nil {
145 t.Fatalf("wspr.idManager.AddAccount(%v, %v) failed; %v", accountName, privateID, err)
146 }
147
148 // Associate with that account
149 method := "POST"
150 path := "/assoc-account"
151
152 origin := "https://my.webapp.com:443"
153 data := assocAccountInput{
154 Name: accountName,
155 Origin: origin,
156 }
157
158 dataJson, err := json.Marshal(data)
159 if err != nil {
160 t.Fatalf("json.Marshal(%v) failed: %v", data, err)
161 }
162
163 dataJsonReader := bytes.NewReader(dataJson)
164 req, err := http.NewRequest(method, path, (dataJsonReader))
165 if err != nil {
166 t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, dataJsonReader, err)
167 }
168
169 resp := httptest.NewRecorder()
170 wspr.handleAssocAccount(resp, req)
171 if resp.Code != 200 {
172 t.Fatalf("Expected handleAssocAccount to return 200 OK, instead got %v", resp)
173 }
174
175 // Verify that idManager has the correct identity for the origin
176 gotID, err := wspr.idManager.Identity(origin)
177 if err != nil {
178 t.Fatalf("wspr.idManager.Identity(%v) failed: %v", origin, err)
179 }
180
181 if gotID == nil {
182 t.Fatalf("Expected wspr.idManager.Identity(%v) to return an valid identity, but got %v", origin, gotID)
183 }
184}
185
186func TestHandleAssocAccountWithMissingAccount(t *testing.T) {
187 wspr, teardown := setup(t)
188 defer teardown()
189
190 method := "POST"
191 path := "/assoc-account"
192
193 accountName := "mock-account"
194 origin := "https://my.webapp.com:443"
195 data := assocAccountInput{
196 Name: accountName,
197 Origin: origin,
198 }
199
200 dataJson, err := json.Marshal(data)
201 if err != nil {
202 t.Fatalf("json.Marshal(%v) failed: %v", data, err)
203 }
204
205 dataJsonReader := bytes.NewReader(dataJson)
206 req, err := http.NewRequest(method, path, (dataJsonReader))
207 if err != nil {
208 t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, dataJsonReader, err)
209 }
210
211 // Verify that the request fails with 400 Bad Request error
212 resp := httptest.NewRecorder()
213 wspr.handleAssocAccount(resp, req)
214 if resp.Code != 400 {
215 t.Fatalf("Expected handleAssocAccount to return 400 error, but got %v", resp)
216 }
217
218 // Verify that idManager has no identities for the origin
219 gotID, err := wspr.idManager.Identity(origin)
220 if err == nil {
221 t.Fatalf("Expected wspr.idManager.Identity(%v) to fail, but got: %v", origin, gotID)
222 }
223
224 if gotID != nil {
225 t.Fatalf("Expected wspr.idManager.Identity(%v) not to return an identity, but got %v", origin, gotID)
226 }
227}