From 949fd019a5683d0e2db3f991e0aa8c271c1c6c1f Mon Sep 17 00:00:00 2001 From: Samuel Bouic Date: Wed, 17 May 2017 16:32:41 +0200 Subject: [PATCH] Add scrollProfile & scrollUsers support --- src/main/java/io/kuzzle/sdk/core/Kuzzle.java | 8 + .../sdk/responses/SecurityDocumentList.java | 11 +- .../java/io/kuzzle/sdk/security/Security.java | 173 ++++++++++++++++- src/main/java/io/kuzzle/sdk/util/Scroll.java | 14 ++ .../KuzzleSecurity/scrollProfilesTest.java | 179 ++++++++++++++++++ .../KuzzleSecurity/scrollUsersTest.java | 179 ++++++++++++++++++ 6 files changed, 555 insertions(+), 9 deletions(-) create mode 100644 src/main/java/io/kuzzle/sdk/util/Scroll.java create mode 100644 src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollProfilesTest.java create mode 100644 src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollUsersTest.java diff --git a/src/main/java/io/kuzzle/sdk/core/Kuzzle.java b/src/main/java/io/kuzzle/sdk/core/Kuzzle.java index 6914150..360c7b2 100644 --- a/src/main/java/io/kuzzle/sdk/core/Kuzzle.java +++ b/src/main/java/io/kuzzle/sdk/core/Kuzzle.java @@ -1318,6 +1318,14 @@ public Kuzzle query(final QueryArgs queryArgs, final JSONObject query, final Opt if (options.getSize() != null) { object.put("size", options.getSize()); } + + if (options.getScroll() != null) { + object.put("scroll", options.getScroll()); + } + + if (options.getScrollId() != null) { + object.put("scrollId", options.getScrollId()); + } } object.put("volatile", _volatile); diff --git a/src/main/java/io/kuzzle/sdk/responses/SecurityDocumentList.java b/src/main/java/io/kuzzle/sdk/responses/SecurityDocumentList.java index ad94b5a..423f697 100644 --- a/src/main/java/io/kuzzle/sdk/responses/SecurityDocumentList.java +++ b/src/main/java/io/kuzzle/sdk/responses/SecurityDocumentList.java @@ -4,14 +4,21 @@ import java.util.List; import io.kuzzle.sdk.security.AbstractSecurityDocument; +import io.kuzzle.sdk.util.Scroll; public class SecurityDocumentList implements KuzzleList { private List documents; private long total; + private Scroll scroll; - public SecurityDocumentList(List roles, long total) { + public SecurityDocumentList(List roles, long total, Scroll scroll) { this.documents = roles; this.total = total; + this.scroll = scroll; + } + + public SecurityDocumentList(List roles, long total) { + this(roles, total, new Scroll()); } public List getDocuments() { @@ -21,4 +28,6 @@ public List getDocuments() { public long getTotal() { return total; } + + public Scroll getScroll() { return scroll; } } diff --git a/src/main/java/io/kuzzle/sdk/security/Security.java b/src/main/java/io/kuzzle/sdk/security/Security.java index f252786..c89981f 100644 --- a/src/main/java/io/kuzzle/sdk/security/Security.java +++ b/src/main/java/io/kuzzle/sdk/security/Security.java @@ -14,6 +14,7 @@ import io.kuzzle.sdk.listeners.ResponseListener; import io.kuzzle.sdk.listeners.OnQueryDoneListener; import io.kuzzle.sdk.responses.SecurityDocumentList; +import io.kuzzle.sdk.util.Scroll; /** @@ -479,7 +480,7 @@ public void onSuccess(JSONObject response) { for (int i = 0; i < policies.length(); i++) { JSONObject formattedPolicy = new JSONObject() - .put("roleId", policies.getJSONObject(i).getString("roleId")); + .put("roleId", policies.getJSONObject(i).getString("roleId")); if (((JSONObject) policies.get(i)).has("restrictedTo")) { formattedPolicy.put("restrictedTo", policies.getJSONObject(i).getJSONArray("restrictedTo")); } @@ -547,14 +548,20 @@ public void onSuccess(JSONObject response) { JSONObject result = response.getJSONObject("result"); JSONArray documents = result.getJSONArray("hits"); int documentsLength = documents.length(); - ArrayList roles = new ArrayList<>(); + ArrayList profiles = new ArrayList<>(); for (int i = 0; i < documentsLength; i++) { JSONObject document = documents.getJSONObject(i); - roles.add(new Profile(Security.this.kuzzle, document.getString("_id"), document.getJSONObject("_source"))); + profiles.add(new Profile(Security.this.kuzzle, document.getString("_id"), document.getJSONObject("_source"))); } - listener.onSuccess(new SecurityDocumentList(roles, result.getLong("total"))); + Scroll scroll = new Scroll(); + + if (result.has("scrollId")) { + scroll.setScrollId(result.getString("scrollId")); + } + + listener.onSuccess(new SecurityDocumentList(profiles, result.getLong("total"), scroll)); } catch (JSONException e) { throw new RuntimeException(e); } @@ -767,6 +774,78 @@ public Security deleteProfile(@NonNull final String id) throws JSONException { return deleteProfile(id, null, null); } + /** + * Returns the next profiles result set with scroll query. + * + * @param scroll - Scroll object + * @param options - Optional arguments + * @param listener - Callback listener + * @throws JSONException the json exception + */ + public void scrollProfiles(final Scroll scroll, final Options options, final ResponseListener listener) throws JSONException { + JSONObject request; + + try { + request = new JSONObject().put("body", new JSONObject()); + } + catch (JSONException e) { + throw new RuntimeException(e); + } + + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + + if (scroll.getScrollId() == null) { + throw new IllegalArgumentException("Security.scrollProfiles: scrollId is required"); + } + + options.setScrollId(scroll.getScrollId()); + + try { + this.kuzzle.query(buildQueryArgs("scrollProfiles"), request, options, new OnQueryDoneListener() { + @Override + public void onSuccess(JSONObject object) { + try { + JSONArray hits = object.getJSONObject("result").getJSONArray("hits"); + ArrayList profiles = new ArrayList<>(); + + for (int i = 0; i < hits.length(); i++) { + JSONObject hit = hits.getJSONObject(i); + Profile profile = new Profile(Security.this.kuzzle, hit.getString("_id"), hit.getJSONObject("_source")); + + profiles.add(profile); + } + + SecurityDocumentList response = new SecurityDocumentList(profiles, hits.length(), scroll); + + listener.onSuccess(response); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + @Override + public void onError(JSONObject error) { + listener.onError(error); + } + }); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the next profiles result set with scroll query. + * + * @param scroll - Scroll object + * @param listener - Callback listener + * @throws JSONException the json exception + */ + public void scrollProfiles(Scroll scroll, final ResponseListener listener) throws JSONException { + this.scrollProfiles(scroll, new Options(), listener); + } + /** * Update profile. * @@ -949,14 +1028,20 @@ public void onSuccess(JSONObject response) { JSONObject result = response.getJSONObject("result"); JSONArray documents = result.getJSONArray("hits"); int documentsLength = documents.length(); - ArrayList roles = new ArrayList<>(); + ArrayList users = new ArrayList<>(); for (int i = 0; i < documentsLength; i++) { JSONObject document = documents.getJSONObject(i); - roles.add(new User(Security.this.kuzzle, document.getString("_id"), document.getJSONObject("_source"))); + users.add(new User(Security.this.kuzzle, document.getString("_id"), document.getJSONObject("_source"))); } - listener.onSuccess(new SecurityDocumentList(roles, result.getLong("total"))); + Scroll scroll = new Scroll(); + + if (result.has("scrollId")) { + scroll.setScrollId(result.getString("scrollId")); + } + + listener.onSuccess(new SecurityDocumentList(users, result.getLong("total"), scroll)); } catch (JSONException e) { throw new RuntimeException(e); } @@ -1251,6 +1336,78 @@ public Security deleteUser(@NonNull final String id) throws JSONException { return deleteUser(id, null, null); } + /** + * Returns the next users result set with scroll query. + * + * @param scroll - Scroll object + * @param options - Optional arguments + * @param listener - Callback listener + * @throws JSONException the json exception + */ + public void scrollUsers(final Scroll scroll, final Options options, final ResponseListener listener) throws JSONException { + JSONObject request; + + try { + request = new JSONObject().put("body", new JSONObject()); + } + catch (JSONException e) { + throw new RuntimeException(e); + } + + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + + if (scroll.getScrollId() == null) { + throw new IllegalArgumentException("Security.scrollUsers: scrollId is required"); + } + + options.setScrollId(scroll.getScrollId()); + + try { + this.kuzzle.query(buildQueryArgs("scrollUsers"), request, options, new OnQueryDoneListener() { + @Override + public void onSuccess(JSONObject object) { + try { + JSONArray hits = object.getJSONObject("result").getJSONArray("hits"); + ArrayList users = new ArrayList<>(); + + for (int i = 0; i < hits.length(); i++) { + JSONObject hit = hits.getJSONObject(i); + User user = new User(Security.this.kuzzle, hit.getString("_id"), hit.getJSONObject("_source")); + + users.add(user); + } + + SecurityDocumentList response = new SecurityDocumentList(users, hits.length(), scroll); + + listener.onSuccess(response); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + @Override + public void onError(JSONObject error) { + listener.onError(error); + } + }); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the next users result set with scroll query. + * + * @param scroll - Scroll object + * @param listener - Callback listener + * @throws JSONException the json exception + */ + public void scrollUsers(Scroll scroll, final ResponseListener listener) throws JSONException { + this.scrollUsers(scroll, new Options(), listener); + } + /** * Update user. * @@ -1469,7 +1626,7 @@ public Security getUserRights(@NonNull final String id, final Options options, @ } try { JSONObject data = new JSONObject() - .put("_id", id); + .put("_id", id); kuzzle.query(buildQueryArgs("getUserRights"), data, options, new OnQueryDoneListener() { @Override public void onSuccess(JSONObject response) { diff --git a/src/main/java/io/kuzzle/sdk/util/Scroll.java b/src/main/java/io/kuzzle/sdk/util/Scroll.java new file mode 100644 index 0000000..36f217b --- /dev/null +++ b/src/main/java/io/kuzzle/sdk/util/Scroll.java @@ -0,0 +1,14 @@ +package io.kuzzle.sdk.util; + + +public class Scroll { + private String scrollId; + + public void setScrollId(String scrollId) { + this.scrollId = scrollId; + } + + public boolean hasScrollId() { return !(scrollId == null); } + + public String getScrollId() { return scrollId; } +} diff --git a/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollProfilesTest.java b/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollProfilesTest.java new file mode 100644 index 0000000..fb2d42f --- /dev/null +++ b/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollProfilesTest.java @@ -0,0 +1,179 @@ +package io.kuzzle.test.security.KuzzleSecurity; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.net.URISyntaxException; + +import io.kuzzle.sdk.core.Kuzzle; +import io.kuzzle.sdk.core.Options; +import io.kuzzle.sdk.enums.Mode; +import io.kuzzle.sdk.listeners.OnQueryDoneListener; +import io.kuzzle.sdk.listeners.ResponseListener; +import io.kuzzle.sdk.responses.SecurityDocumentList; +import io.kuzzle.sdk.security.Security; +import io.kuzzle.sdk.state.States; +import io.kuzzle.sdk.util.Scroll; +import io.kuzzle.test.testUtils.KuzzleExtend; +import io.socket.client.Socket; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class scrollProfilesTest { + private Kuzzle kuzzle; + private Security security; + private ResponseListener listener; + private Options options; + private Scroll scroll; + private String scrollId; + + @Before + public void setUp() throws URISyntaxException { + Options opts = new Options(); + opts.setConnect(Mode.MANUAL); + KuzzleExtend extended = new KuzzleExtend("localhost", opts, null); + extended.setSocket(mock(Socket.class)); + extended.setState(States.CONNECTED); + kuzzle = spy(extended); + when(kuzzle.getHeaders()).thenReturn(new JSONObject()); + + security = new Security(kuzzle); + listener = mock(ResponseListener.class); + options = mock(Options.class); + scroll = new Scroll(); + scrollId = "f00ba5"; + } + + @Test(expected = IllegalArgumentException.class) + public void testScrollProfilesNoScrollId() throws JSONException { + security.scrollProfiles(scroll, null, listener); + } + + @Test(expected = IllegalArgumentException.class) + public void testScrollProfilesIllegalListener() throws JSONException { + scroll.setScrollId(scrollId); + security.scrollProfiles(scroll, null); + } + + @Test + public void checkSignaturesVariants() throws JSONException { + security = spy(security); + scroll.setScrollId(scrollId); + + security.scrollProfiles(scroll, listener); + verify(security).scrollProfiles(eq(scroll), eq(listener)); + + security.scrollProfiles(scroll, options, listener); + verify(security).scrollProfiles(eq(scroll), eq(options), eq(listener)); + } + + @Test(expected = RuntimeException.class) + public void testScrollProfilesQueryException() throws JSONException { + scroll.setScrollId(scrollId); + doThrow(JSONException.class).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + security.scrollProfiles(scroll, listener); + } + + @Test(expected = RuntimeException.class) + public void testScrollProfilesException() throws JSONException { + scroll.setScrollId(scrollId); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ((OnQueryDoneListener) invocation.getArguments()[3]).onSuccess(new JSONObject().put("result", new JSONObject().put("count", 42))); + return null; + } + }).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + doThrow(JSONException.class).when(listener).onSuccess(any(Integer.class)); + security.scrollProfiles(scroll, listener); + } + + @Test + public void testScrollProfiles() throws JSONException { + scroll.setScrollId("f00ba5"); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + JSONObject response = new JSONObject("{\"result\": {\n" + + " \"_shards\": {\n" + + " \"failed\": 0,\n" + + " \"successful\": 5,\n" + + " \"total\": 5\n" + + " },\n" + + " \"hits\": [\n" + + " {\n" + + " \"_id\": \"AVJAwyDMZAGQHg9Dhfw2\",\n" + + " \"_index\": \"cabble\",\n" + + " \"_score\": 1,\n" + + " \"_source\": {\n" + + " \"pos\": {\n" + + " \"lat\": 43.6073821,\n" + + " \"lon\": 3.9130721\n" + + " },\n" + + " \"sibling\": \"none\",\n" + + " \"status\": \"idle\",\n" + + " \"type\": \"customer\"\n" + + " },\n" + + " \"_type\": \"users\"\n" + + " },\n" + + " {\n" + + " \"_id\": \"AVJAwyOvZAGQHg9Dhfw3\",\n" + + " \"_index\": \"cabble\",\n" + + " \"_score\": 1,\n" + + " \"_source\": {\n" + + " \"pos\": {\n" + + " \"lat\": 43.6073683,\n" + + " \"lon\": 3.8999983\n" + + " },\n" + + " \"sibling\": \"none\",\n" + + " \"status\": \"idle\",\n" + + " \"type\": \"cab\"\n" + + " },\n" + + " \"_type\": \"users\"\n" + + " }\n" + + " ],\n" + + " \"max_score\": 1,\n" + + " \"timed_out\": false,\n" + + " \"took\": 307,\n" + + " \"total\": 2\n" + + " }" + + "}"); + + ((OnQueryDoneListener) invocation.getArguments()[3]).onSuccess(response); + ((OnQueryDoneListener) invocation.getArguments()[3]).onError(new JSONObject()); + return null; + } + }).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + + security.scrollProfiles(scroll, new ResponseListener() { + @Override + public void onSuccess(SecurityDocumentList result) { + assertEquals(result.getTotal(), 2); + assertEquals(result.getDocuments().get(1).getId(), "AVJAwyOvZAGQHg9Dhfw3"); + } + + @Override + public void onError(JSONObject error) { + } + }); + security.scrollProfiles(scroll, mock(ResponseListener.class)); + ArgumentCaptor argument = ArgumentCaptor.forClass(Kuzzle.QueryArgs.class); + verify(kuzzle, times(2)).query((Kuzzle.QueryArgs) argument.capture(), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + assertEquals(((Kuzzle.QueryArgs) argument.getValue()).controller, "security"); + assertEquals(((Kuzzle.QueryArgs) argument.getValue()).action, "scrollProfiles"); + } +} diff --git a/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollUsersTest.java b/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollUsersTest.java new file mode 100644 index 0000000..9c1cf43 --- /dev/null +++ b/src/test/java/io/kuzzle/test/security/KuzzleSecurity/scrollUsersTest.java @@ -0,0 +1,179 @@ +package io.kuzzle.test.security.KuzzleSecurity; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.net.URISyntaxException; + +import io.kuzzle.sdk.core.Kuzzle; +import io.kuzzle.sdk.core.Options; +import io.kuzzle.sdk.enums.Mode; +import io.kuzzle.sdk.listeners.OnQueryDoneListener; +import io.kuzzle.sdk.listeners.ResponseListener; +import io.kuzzle.sdk.responses.SecurityDocumentList; +import io.kuzzle.sdk.security.Security; +import io.kuzzle.sdk.state.States; +import io.kuzzle.sdk.util.Scroll; +import io.kuzzle.test.testUtils.KuzzleExtend; +import io.socket.client.Socket; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class scrollUsersTest { + private Kuzzle kuzzle; + private Security security; + private ResponseListener listener; + private Options options; + private Scroll scroll; + private String scrollId; + + @Before + public void setUp() throws URISyntaxException { + Options opts = new Options(); + opts.setConnect(Mode.MANUAL); + KuzzleExtend extended = new KuzzleExtend("localhost", opts, null); + extended.setSocket(mock(Socket.class)); + extended.setState(States.CONNECTED); + kuzzle = spy(extended); + when(kuzzle.getHeaders()).thenReturn(new JSONObject()); + + security = new Security(kuzzle); + listener = mock(ResponseListener.class); + options = mock(Options.class); + scroll = new Scroll(); + scrollId = "f00ba5"; + } + + @Test(expected = IllegalArgumentException.class) + public void testScrollUsersNoScrollId() throws JSONException { + security.scrollUsers(scroll, null, listener); + } + + @Test(expected = IllegalArgumentException.class) + public void testScrollUsersIllegalListener() throws JSONException { + scroll.setScrollId(scrollId); + security.scrollUsers(scroll, null); + } + + @Test + public void checkSignaturesVariants() throws JSONException { + security = spy(security); + scroll.setScrollId(scrollId); + + security.scrollUsers(scroll, listener); + verify(security).scrollUsers(eq(scroll), eq(listener)); + + security.scrollUsers(scroll, options, listener); + verify(security).scrollUsers(eq(scroll), eq(options), eq(listener)); + } + + @Test(expected = RuntimeException.class) + public void testScrollUsersQueryException() throws JSONException { + scroll.setScrollId(scrollId); + doThrow(JSONException.class).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + security.scrollUsers(scroll, listener); + } + + @Test(expected = RuntimeException.class) + public void testScrollUsersException() throws JSONException { + scroll.setScrollId(scrollId); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ((OnQueryDoneListener) invocation.getArguments()[3]).onSuccess(new JSONObject().put("result", new JSONObject().put("count", 42))); + return null; + } + }).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + doThrow(JSONException.class).when(listener).onSuccess(any(Integer.class)); + security.scrollUsers(scroll, listener); + } + + @Test + public void testScrollUsers() throws JSONException { + scroll.setScrollId("f00ba5"); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + JSONObject response = new JSONObject("{\"result\": {\n" + + " \"_shards\": {\n" + + " \"failed\": 0,\n" + + " \"successful\": 5,\n" + + " \"total\": 5\n" + + " },\n" + + " \"hits\": [\n" + + " {\n" + + " \"_id\": \"AVJAwyDMZAGQHg9Dhfw2\",\n" + + " \"_index\": \"cabble\",\n" + + " \"_score\": 1,\n" + + " \"_source\": {\n" + + " \"pos\": {\n" + + " \"lat\": 43.6073821,\n" + + " \"lon\": 3.9130721\n" + + " },\n" + + " \"sibling\": \"none\",\n" + + " \"status\": \"idle\",\n" + + " \"type\": \"customer\"\n" + + " },\n" + + " \"_type\": \"users\"\n" + + " },\n" + + " {\n" + + " \"_id\": \"AVJAwyOvZAGQHg9Dhfw3\",\n" + + " \"_index\": \"cabble\",\n" + + " \"_score\": 1,\n" + + " \"_source\": {\n" + + " \"pos\": {\n" + + " \"lat\": 43.6073683,\n" + + " \"lon\": 3.8999983\n" + + " },\n" + + " \"sibling\": \"none\",\n" + + " \"status\": \"idle\",\n" + + " \"type\": \"cab\"\n" + + " },\n" + + " \"_type\": \"users\"\n" + + " }\n" + + " ],\n" + + " \"max_score\": 1,\n" + + " \"timed_out\": false,\n" + + " \"took\": 307,\n" + + " \"total\": 2\n" + + " }" + + "}"); + + ((OnQueryDoneListener) invocation.getArguments()[3]).onSuccess(response); + ((OnQueryDoneListener) invocation.getArguments()[3]).onError(new JSONObject()); + return null; + } + }).when(kuzzle).query(any(Kuzzle.QueryArgs.class), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + + security.scrollUsers(scroll, new ResponseListener() { + @Override + public void onSuccess(SecurityDocumentList result) { + assertEquals(result.getTotal(), 2); + assertEquals(result.getDocuments().get(1).getId(), "AVJAwyOvZAGQHg9Dhfw3"); + } + + @Override + public void onError(JSONObject error) { + } + }); + security.scrollUsers(scroll, mock(ResponseListener.class)); + ArgumentCaptor argument = ArgumentCaptor.forClass(Kuzzle.QueryArgs.class); + verify(kuzzle, times(2)).query((Kuzzle.QueryArgs) argument.capture(), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + assertEquals(((Kuzzle.QueryArgs) argument.getValue()).controller, "security"); + assertEquals(((Kuzzle.QueryArgs) argument.getValue()).action, "scrollUsers"); + } +}