[IOT-1556] Changes in cloud according to the stateless request/response model (group...
[platform/upstream/iotivity.git] / cloud / account / src / test / java / org / iotivity / cloud / accountserver / resources / acl / invite / InviteResourceTest.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.resources.acl.invite;
23
24 import static java.util.concurrent.TimeUnit.SECONDS;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.Mockito.mock;
28
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.HashMap;
32 import java.util.concurrent.CountDownLatch;
33
34 import org.iotivity.cloud.accountserver.Constants;
35 import org.iotivity.cloud.accountserver.db.MongoDB;
36 import org.iotivity.cloud.accountserver.resources.acl.group.GroupResource;
37 import org.iotivity.cloud.base.device.CoapDevice;
38 import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException;
39 import org.iotivity.cloud.base.protocols.IRequest;
40 import org.iotivity.cloud.base.protocols.IResponse;
41 import org.iotivity.cloud.base.protocols.MessageBuilder;
42 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
43 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
44 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
45 import org.iotivity.cloud.base.protocols.enums.Observe;
46 import org.iotivity.cloud.base.protocols.enums.RequestMethod;
47 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
48 import org.iotivity.cloud.util.Cbor;
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.mockito.Mockito;
52 import org.mockito.invocation.InvocationOnMock;
53 import org.mockito.stubbing.Answer;
54
55 public class InviteResourceTest {
56     private static final String           INVITE_URI        = Constants.INVITE_FULL_URI;
57     private static final String           GROUP_URI         = Constants.GROUP_FULL_URI;
58
59     private static final String           TEST_INVITE_USER  = "u0001";
60     private static final String           TEST_INVITED_USER = "u0002";
61     private static final String           TEST_GROUP_ID     = "g0001";
62
63     private String                        mInvitedGroupId   = null;
64
65     private InviteResource                mInviteResource   = null;
66
67     private GroupResource                 mGroupResource    = new GroupResource();
68
69     private CountDownLatch                mLatch            = null;
70
71     private CoapDevice                    mMockDevice       = null;
72     private IResponse                     mResponse         = null;
73
74     private Cbor<HashMap<String, Object>> mCbor             = new Cbor<>();
75
76     @Before
77     public void setUp() throws Exception {
78
79         mInviteResource = new InviteResource();
80
81         mLatch = new CountDownLatch(1);
82
83         mMockDevice = Mockito.mock(CoapDevice.class);
84
85         mResponse = null;
86
87         // reset data base
88         MongoDB mongoDB = new MongoDB(Constants.DB_NAME);
89         mongoDB.deleteTable(Constants.INVITE_TABLE);
90         mongoDB.createTable(Constants.INVITE_TABLE);
91
92         Mockito.doAnswer(new Answer<Object>() {
93             @Override
94             public CoapResponse answer(InvocationOnMock invocation)
95                     throws Throwable {
96                 Object[] args = invocation.getArguments();
97                 CoapResponse resp = (CoapResponse) args[0];
98                 mResponse = resp;
99
100                 if (resp.getPayloadSize() != 0) {
101
102                     HashMap<String, Object> payloadData = mCbor
103                             .parsePayloadFromCbor(resp.getPayload(),
104                                     HashMap.class);
105
106                     if (payloadData.containsKey(Constants.REQ_GROUP_ID)) {
107                         mInvitedGroupId = (String) payloadData
108                                 .get(Constants.REQ_GROUP_ID);
109                     }
110                 }
111
112                 mLatch.countDown();
113
114                 return resp;
115             }
116         }).when(mMockDevice).sendResponse(Mockito.anyObject());
117
118     }
119
120     @Test
121     public void testSendInvitation() throws Exception {
122
123         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
124
125         assertTrue(mLatch.await(1L, SECONDS));
126         assertEquals(mResponse.getStatus(), ResponseStatus.CHANGED);
127     }
128
129     @Test(expected = PreconditionFailedException.class)
130     public void testSendInvitationWithoutGid() throws Exception {
131
132         sendInvitation(null, TEST_INVITED_USER);
133     }
134
135     @Test(expected = PreconditionFailedException.class)
136     public void testSendInvitationWithoutMid() throws Exception {
137
138         sendInvitation(TEST_GROUP_ID, null);
139     }
140
141     @Test
142     public void testInviteUserObserveInvition() throws Exception {
143
144         CountDownLatch latchInviteUser = new CountDownLatch(2);
145
146         CoapDevice mockInviteUser = mock(CoapDevice.class);
147
148         // invite user callback
149         Mockito.doAnswer(new Answer<Object>() {
150             @Override
151             public CoapResponse answer(InvocationOnMock invocation)
152                     throws Throwable {
153                 Object[] args = invocation.getArguments();
154                 CoapResponse resp = (CoapResponse) args[0];
155
156                 latchInviteUser.countDown();
157
158                 // check observe notification response
159                 if (latchInviteUser.getCount() == 0) {
160
161                     assertEquals(resp.getStatus(), ResponseStatus.CONTENT);
162                     assertTrue(
163                             checkResponsePayload(resp, Constants.RESP_INVITE));
164                     assertTrue(checkInviteInfo(resp.getPayload(),
165                             Constants.RESP_INVITE, TEST_GROUP_ID,
166                             TEST_INVITED_USER));
167                 }
168
169                 return resp;
170             }
171         }).when(mockInviteUser).sendResponse(Mockito.anyObject());
172
173         getInvitation(TEST_INVITE_USER, mockInviteUser, Observe.SUBSCRIBE);
174         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
175
176         assertTrue(latchInviteUser.await(2L, SECONDS));
177     }
178
179     @Test
180     public void testInvitedUserObserveInvitation() throws Exception {
181
182         CountDownLatch latchInvitedUser = new CountDownLatch(2);
183
184         CoapDevice mockInvitedUser = mock(CoapDevice.class);
185
186         // invited user callback
187         Mockito.doAnswer(new Answer<Object>() {
188             @Override
189             public CoapResponse answer(InvocationOnMock invocation)
190                     throws Throwable {
191                 Object[] args = invocation.getArguments();
192                 CoapResponse resp = (CoapResponse) args[0];
193
194                 latchInvitedUser.countDown();
195
196                 // check observe notification response
197                 if (latchInvitedUser.getCount() == 0) {
198
199                     assertEquals(resp.getStatus(), ResponseStatus.CONTENT);
200                     assertTrue(
201                             checkResponsePayload(resp, Constants.RESP_INVITED));
202                     assertTrue(checkInviteInfo(resp.getPayload(),
203                             Constants.RESP_INVITED, TEST_GROUP_ID,
204                             TEST_INVITE_USER));
205                 }
206
207                 return resp;
208             }
209         }).when(mockInvitedUser).sendResponse(Mockito.anyObject());
210
211         getInvitation(TEST_INVITED_USER, mockInvitedUser, Observe.SUBSCRIBE);
212         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
213
214         assertTrue(latchInvitedUser.await(2L, SECONDS));
215     }
216
217     @Test
218     public void testInviteUserCancelObserveInvitation() throws Exception {
219
220         getInvitation(TEST_INVITE_USER, mMockDevice, Observe.SUBSCRIBE);
221         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
222
223         getInvitation(TEST_INVITE_USER, mMockDevice, Observe.UNSUBSCRIBE);
224
225         assertEquals(mResponse.getStatus(), ResponseStatus.CONTENT);
226         assertTrue(checkInviteInfo(mResponse.getPayload(),
227                 Constants.RESP_INVITE, TEST_GROUP_ID, TEST_INVITED_USER));
228     }
229
230     @Test
231     public void testInvitedUserCancelObserveInvitation() throws Exception {
232
233         getInvitation(TEST_INVITED_USER, mMockDevice, Observe.SUBSCRIBE);
234         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
235
236         getInvitation(TEST_INVITED_USER, mMockDevice, Observe.UNSUBSCRIBE);
237
238         assertEquals(mResponse.getStatus(), ResponseStatus.CONTENT);
239         assertTrue(checkInviteInfo(mResponse.getPayload(),
240                 Constants.RESP_INVITED, TEST_GROUP_ID, TEST_INVITE_USER));
241     }
242
243     @Test
244     public void testInviteUserGetInvitation() throws Exception {
245
246         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
247
248         getInvitation(TEST_INVITE_USER, mMockDevice, Observe.NOTHING);
249
250         assertEquals(mResponse.getStatus(), ResponseStatus.CONTENT);
251         assertTrue(checkInviteInfo(mResponse.getPayload(),
252                 Constants.RESP_INVITE, TEST_GROUP_ID, TEST_INVITED_USER));
253     }
254
255     @Test
256     public void testInvitedUserGetInvitation() throws Exception {
257
258         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
259
260         getInvitation(TEST_INVITED_USER, mMockDevice, Observe.NOTHING);
261
262         assertEquals(mResponse.getStatus(), ResponseStatus.CONTENT);
263         assertTrue(checkInviteInfo(mResponse.getPayload(),
264                 Constants.RESP_INVITED, TEST_GROUP_ID, TEST_INVITE_USER));
265     }
266
267     @Test
268     public void testDeleteInvitationForAccept() throws Exception {
269
270         createGroup(mMockDevice, TEST_INVITE_USER, "Public", null);
271         sendInvitation(mInvitedGroupId, TEST_INVITED_USER);
272
273         deleteInvitationWithQuery(mInvitedGroupId, TEST_INVITED_USER, true);
274
275         assertTrue(mLatch.await(1L, SECONDS));
276         assertEquals(mResponse.getStatus(), ResponseStatus.DELETED);
277
278     }
279
280     @Test
281     public void testDeleteInvitationForDeny() throws Exception {
282
283         createGroup(mMockDevice, TEST_INVITE_USER, "Public", null);
284         sendInvitation(mInvitedGroupId, TEST_INVITED_USER);
285
286         deleteInvitationWithQuery(mInvitedGroupId, TEST_INVITED_USER, false);
287
288         assertTrue(mLatch.await(1L, SECONDS));
289         assertEquals(mResponse.getStatus(), ResponseStatus.DELETED);
290     }
291
292     @Test
293     public void testCancelInvitation() throws Exception {
294
295         sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER);
296
297         deleteInvitation(TEST_GROUP_ID, TEST_INVITE_USER, TEST_INVITED_USER);
298
299         assertTrue(mLatch.await(1L, SECONDS));
300         assertEquals(mResponse.getStatus(), ResponseStatus.DELETED);
301     }
302
303     private void sendInvitation(String gid, String mid) {
304
305         IRequest request = makeSendInvitationRequest(gid, mid);
306
307         mInviteResource.onDefaultRequestReceived(mMockDevice, request);
308     }
309
310     private void deleteInvitation(String gid, String uid, String mid) {
311
312         String uriQuery = Constants.REQ_GROUP_ID + "=" + gid + ";"
313                 + Constants.REQ_UUID_ID + "=" + uid + ";" + Constants.REQ_MEMBER
314                 + "=" + mid;
315
316         IRequest request = MessageBuilder.createRequest(RequestMethod.DELETE,
317                 INVITE_URI, uriQuery);
318
319         mInviteResource.onDefaultRequestReceived(mMockDevice, request);
320     }
321
322     private void getInvitation(String uid, CoapDevice device,
323             Observe observeOpt) {
324
325         String uriQuery = Constants.REQ_UUID_ID + "=" + uid;
326         IRequest request = MessageBuilder.createRequest(RequestMethod.GET,
327                 INVITE_URI, uriQuery);
328
329         if (observeOpt.equals(Observe.NOTHING) == false) {
330             ((CoapRequest) request).setObserve(observeOpt);
331         }
332
333         mInviteResource.onDefaultRequestReceived(device, request);
334     }
335
336     private IRequest makeSendInvitationRequest(String gid, String mid) {
337
338         HashMap<String, Object> invitation = new HashMap<>();
339         invitation.put(Constants.REQ_GROUP_ID, gid);
340         invitation.put(Constants.REQ_MEMBER, mid);
341
342         HashMap<String, Object> payload = new HashMap<>();
343         payload.put(Constants.REQ_UUID_ID, TEST_INVITE_USER);
344         payload.put(Constants.REQ_INVITE, Arrays.asList(invitation));
345
346         return MessageBuilder.createRequest(RequestMethod.POST, INVITE_URI,
347                 null, ContentFormat.APPLICATION_CBOR,
348                 mCbor.encodingPayloadToCbor(payload));
349     }
350
351     private boolean checkResponsePayload(IResponse response,
352             String propertyName) {
353
354         HashMap<String, Object> payloadData = mCbor
355                 .parsePayloadFromCbor(response.getPayload(), HashMap.class);
356
357         return payloadData.get(propertyName) != null ? true : false;
358     }
359
360     private boolean checkInviteInfo(byte[] payload, String propertyKey,
361             String gid, String mid) {
362
363         HashMap<String, Object> paredPayload = mCbor
364                 .parsePayloadFromCbor(payload, HashMap.class);
365
366         @SuppressWarnings("unchecked")
367         ArrayList<HashMap<String, Object>> invitationList = (ArrayList<HashMap<String, Object>>) paredPayload
368                 .get(propertyKey);
369
370         for (HashMap<String, Object> invitation : invitationList) {
371
372             if (invitation.get(Constants.REQ_GROUP_ID).equals(gid)
373                     && invitation.get(Constants.REQ_MEMBER).equals(mid)) {
374
375                 return true;
376             }
377         }
378
379         return false;
380     }
381
382     private void deleteInvitationWithQuery(String gid, String uid,
383             boolean accept) {
384
385         int acceptInt = 0;
386
387         if (accept)
388             acceptInt = 1;
389
390         String uriQuery = Constants.REQ_GROUP_ID + "=" + gid + ";"
391                 + Constants.REQ_UUID_ID + "=" + uid + ";"
392                 + Constants.REQ_INVITE_ACCEPT + "=" + acceptInt;
393
394         IRequest request = MessageBuilder.createRequest(RequestMethod.DELETE,
395                 INVITE_URI, uriQuery);
396
397         mInviteResource.onDefaultRequestReceived(mMockDevice, request);
398     }
399
400     private void createGroup(CoapDevice device, String uid, String gname,
401             String parent) throws Exception {
402         System.out.println("-----Create Group");
403         IRequest request = null;
404         HashMap<String, Object> payloadData = new HashMap<String, Object>();
405         payloadData.put(Constants.KEYFIELD_GROUP_NAME, gname);
406         payloadData.put(Constants.KEYFIELD_GROUP_PARENT, parent);
407         payloadData.put(Constants.KEYFIELD_GROUP_MEMBERS,
408                 new ArrayList<String>(Arrays.asList(uid)));
409         payloadData.put(Constants.KEYFIELD_OID, uid);
410         request = MessageBuilder.createRequest(RequestMethod.POST, GROUP_URI,
411                 Constants.KEYFIELD_UID + "=" + uid,
412                 ContentFormat.APPLICATION_CBOR,
413                 mCbor.encodingPayloadToCbor(payloadData));
414         mGroupResource.onDefaultRequestReceived(device, request);
415     }
416 }