jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/337508 )
Change subject: Retrofit ReadingListPageInfoTask and update caller to query in
batches
......................................................................
Retrofit ReadingListPageInfoTask and update caller to query in batches
Bug: T152408
Bug: T155502
Change-Id: Icb66a97590323351992b18aa713ec30a8f03578f
---
M app/src/main/java/org/wikipedia/Constants.java
M app/src/main/java/org/wikipedia/readinglist/ReadingListHeaderView.java
D app/src/main/java/org/wikipedia/readinglist/ReadingListImageFetcher.java
M app/src/main/java/org/wikipedia/readinglist/ReadingListItemView.java
A app/src/main/java/org/wikipedia/readinglist/ReadingListPageDetailFetcher.java
A app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoClient.java
D app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoTask.java
A app/src/main/java/org/wikipedia/util/BatchUtil.java
A app/src/test/java/org/wikipedia/readinglist/ReadingListPageInfoClientTest.java
A app/src/test/java/org/wikipedia/util/BatchUtilTest.java
A app/src/test/res/raw/reading_list_page_info.json
11 files changed, 466 insertions(+), 149 deletions(-)
Approvals:
Niedzielski: Looks good to me, approved
jenkins-bot: Verified
diff --git a/app/src/main/java/org/wikipedia/Constants.java
b/app/src/main/java/org/wikipedia/Constants.java
index 97d2f71..8a80959 100644
--- a/app/src/main/java/org/wikipedia/Constants.java
+++ b/app/src/main/java/org/wikipedia/Constants.java
@@ -31,6 +31,7 @@
public static final int MAX_SUGGESTION_RESULTS = 3;
public static final int SUGGESTION_REQUEST_ITEMS = 5;
+ public static final int API_QUERY_MAX_TITLES = 50;
public static final int PREFERRED_THUMB_SIZE = 320;
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListHeaderView.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListHeaderView.java
index a42741d..7ab4cca 100644
--- a/app/src/main/java/org/wikipedia/readinglist/ReadingListHeaderView.java
+++ b/app/src/main/java/org/wikipedia/readinglist/ReadingListHeaderView.java
@@ -91,17 +91,15 @@
}
private void getThumbnails() {
- ReadingListImageFetcher.getThumbnails(readingList, new
ReadingListImageFetcher.CompleteListener() {
- @Override
- public void onComplete() {
+ ReadingListPageDetailFetcher.updateInfo(readingList, new
ReadingListPageDetailFetcher.Callback() {
+ @Override public void success() {
if (getWindowToken() == null) {
return;
}
updateThumbnails();
}
- @Override
- public void onError(Throwable e) {
+ @Override public void failure(Throwable e) {
}
});
updateThumbnails();
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListImageFetcher.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListImageFetcher.java
deleted file mode 100644
index e30edf7..0000000
--- a/app/src/main/java/org/wikipedia/readinglist/ReadingListImageFetcher.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.wikipedia.readinglist;
-
-import android.support.annotation.NonNull;
-import android.text.TextUtils;
-
-import org.mediawiki.api.json.Api;
-import org.wikipedia.Constants;
-import org.wikipedia.WikipediaApp;
-import org.wikipedia.dataclient.WikiSite;
-import org.wikipedia.page.PageTitle;
-import org.wikipedia.readinglist.page.ReadingListPage;
-import org.wikipedia.readinglist.page.database.ReadingListDaoProxy;
-import org.wikipedia.readinglist.page.database.ReadingListPageDao;
-import org.wikipedia.util.log.L;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public final class ReadingListImageFetcher {
-
- public interface CompleteListener {
- void onComplete();
- void onError(Throwable e);
- }
-
- public static void getThumbnails(final ReadingList readingList,
- @NonNull final CompleteListener listener)
{
- Map<WikiSite, List<PageTitle>> titlesPerSite = new HashMap<>();
- for (ReadingListPage page : readingList.getPages()) {
- if (TextUtils.isEmpty(page.thumbnailUrl()) ||
TextUtils.isEmpty(page.description())) {
- PageTitle title = ReadingListDaoProxy.pageTitle(page);
- WikiSite wikiKey = null;
- for (WikiSite wiki : titlesPerSite.keySet()) {
- if (wiki.equals(title.getWikiSite())) {
- wikiKey = wiki;
- break;
- }
- }
- if (wikiKey == null) {
- wikiKey = title.getWikiSite();
- titlesPerSite.put(wikiKey, new ArrayList<PageTitle>());
- }
- titlesPerSite.get(wikiKey).add(title);
- }
- }
-
- for (WikiSite wiki : titlesPerSite.keySet()) {
- getThumbnailsForTitles(readingList, titlesPerSite.get(wiki),
listener);
- }
- }
-
- private static void getThumbnailsForTitles(final ReadingList readingList,
- @NonNull final List<PageTitle>
titles,
- @NonNull final CompleteListener
listener) {
- WikiSite wiki = titles.get(0).getWikiSite();
- Api api =
WikipediaApp.getInstance().getAPIForSite(titles.get(0).getWikiSite());
- new ReadingListPageInfoTask(api, wiki, titles,
Constants.PREFERRED_THUMB_SIZE) {
- @Override
- public void onFinish(Map<PageTitle, Void> result) {
- for (PageTitle title : titles) {
- if (result.containsKey(title)) {
- for (ReadingListPage page : readingList.getPages()) {
- if (title.getDisplayText().equals(page.title())) {
- page.setThumbnailUrl(title.getThumbUrl());
- page.setDescription(title.getDescription());
- ReadingListPageDao.instance().upsert(page);
- }
- }
- }
- }
- listener.onComplete();
- }
-
- @Override
- public void onCatch(Throwable caught) {
- L.w(caught);
- listener.onError(caught);
- }
- }.execute();
- }
-
- private ReadingListImageFetcher() {
- }
-}
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListItemView.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListItemView.java
index 3003c0f..e9b2ee5 100644
--- a/app/src/main/java/org/wikipedia/readinglist/ReadingListItemView.java
+++ b/app/src/main/java/org/wikipedia/readinglist/ReadingListItemView.java
@@ -130,17 +130,15 @@
}
private void getThumbnails() {
- ReadingListImageFetcher.getThumbnails(readingList, new
ReadingListImageFetcher.CompleteListener() {
- @Override
- public void onComplete() {
+ ReadingListPageDetailFetcher.updateInfo(readingList, new
ReadingListPageDetailFetcher.Callback() {
+ @Override public void success() {
if (getWindowToken() == null) {
return;
}
updateThumbnails();
}
- @Override
- public void onError(Throwable e) {
+ @Override public void failure(@NonNull Throwable e) {
}
});
updateThumbnails();
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListPageDetailFetcher.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListPageDetailFetcher.java
new file mode 100644
index 0000000..b726154
--- /dev/null
+++
b/app/src/main/java/org/wikipedia/readinglist/ReadingListPageDetailFetcher.java
@@ -0,0 +1,130 @@
+package org.wikipedia.readinglist;
+
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.dataclient.mwapi.MwQueryPage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.page.PageTitle;
+import org.wikipedia.readinglist.page.ReadingListPage;
+import org.wikipedia.readinglist.page.database.ReadingListDaoProxy;
+import org.wikipedia.readinglist.page.database.ReadingListPageDao;
+import org.wikipedia.util.BatchUtil;
+import org.wikipedia.util.log.L;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import retrofit2.Call;
+
+final class ReadingListPageDetailFetcher {
+ public interface Callback{
+ void success();
+ void failure(Throwable caught);
+ }
+
+ private static ReadingListPageInfoClient CLIENT = new
ReadingListPageInfoClient();
+
+ static void updateInfo(@NonNull ReadingList readingList, @NonNull final
Callback cb) {
+ Map<WikiSite, List<PageTitle>> titlesPerSite = new HashMap<>();
+ for (ReadingListPage page : readingList.getPages()) {
+ if (TextUtils.isEmpty(page.thumbnailUrl()) ||
TextUtils.isEmpty(page.description())) {
+ PageTitle title = ReadingListDaoProxy.pageTitle(page);
+ WikiSite wikiKey = null;
+ for (WikiSite wiki : titlesPerSite.keySet()) {
+ if (wiki.equals(title.getWikiSite())) {
+ wikiKey = wiki;
+ break;
+ }
+ }
+ if (wikiKey == null) {
+ wikiKey = title.getWikiSite();
+ titlesPerSite.put(wikiKey, new ArrayList<PageTitle>());
+ }
+ titlesPerSite.get(wikiKey).add(title);
+ }
+ }
+
+ for (WikiSite wiki : titlesPerSite.keySet()) {
+ getInfoForTitles(readingList, titlesPerSite.get(wiki), wiki, cb);
+ }
+ }
+
+ private static void getInfoForTitles(@NonNull final ReadingList
readingList,
+ @NonNull final List<PageTitle> titles,
+ @NonNull WikiSite wiki, @NonNull
final Callback cb) {
+ BatchUtil.makeBatches(titles, new RequestHandler(), new
PagesForWikiCallback(readingList, wiki, cb));
+ }
+
+ private static class RequestHandler implements
BatchUtil.Handler<MwQueryPage> {
+ private final List<MwQueryPage> results = new ArrayList<>();
+
+ @Override public void handleBatch(@NonNull final List<PageTitle>
titles, final int total,
+ final
BatchUtil.Callback<MwQueryPage> outerCallback) {
+ CLIENT.request(titles.get(0).getWikiSite(), titles, new
ReadingListPageInfoClient.Callback() {
+ @Override public void success(@NonNull
Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call,
+ @NonNull List<MwQueryPage>
queryResults) {
+ results.addAll(queryResults);
+
+ if (results.size() == total) {
+ outerCallback.success(results);
+ }
+ }
+
+ @Override public void failure(@NonNull
Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call,
+ @NonNull Throwable caught) {
+ L.w(caught);
+ outerCallback.failure(caught);
+ }
+ });
+ }
+ }
+
+ private static class PagesForWikiCallback implements
BatchUtil.Callback<MwQueryPage> {
+ @NonNull private ReadingList readingList;
+ @NonNull private WikiSite wiki;
+ @NonNull private Callback callback;
+
+ PagesForWikiCallback(@NonNull final ReadingList readingList, @NonNull
WikiSite wiki,
+ @NonNull final Callback cb) {
+ this.readingList = readingList;
+ this.wiki = wiki;
+ this.callback = cb;
+ }
+
+ @Override public void success(@NonNull List<MwQueryPage> result) {
+ Map<String, MwQueryPage> resultMap = makeQueryPageMap(result);
+ for (ReadingListPage page : readingList.getPages()) {
+ if ((isFromRequestWiki(page)) &&
resultMap.containsKey(page.title())) {
+
page.setThumbnailUrl(resultMap.get(page.title()).thumbUrl());
+
page.setDescription(resultMap.get(page.title()).description());
+ ReadingListPageDao.instance().upsert(page);
+ }
+ }
+ callback.success();
+ }
+
+ @Override public void failure(@NonNull Throwable caught) {
+ callback.failure(caught);
+ L.w(caught);
+ }
+
+ @NonNull private Map<String, MwQueryPage> makeQueryPageMap(@NonNull
List<MwQueryPage> pages) {
+ Map<String, MwQueryPage> result = new HashMap<>();
+ for (MwQueryPage page : pages) {
+ result.put(page.title(), page);
+ }
+ return result;
+ }
+
+ private boolean isFromRequestWiki(@NonNull ReadingListPage page) {
+ return wiki.equals(page.wikiSite());
+ }
+ }
+
+ private ReadingListPageDetailFetcher() {
+ }
+}
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoClient.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoClient.java
new file mode 100644
index 0000000..57b7e3d
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoClient.java
@@ -0,0 +1,86 @@
+package org.wikipedia.readinglist;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+
+import org.wikipedia.Constants;
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.dataclient.mwapi.MwException;
+import org.wikipedia.dataclient.mwapi.MwQueryPage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.dataclient.retrofit.MwCachedService;
+import org.wikipedia.dataclient.retrofit.RetrofitException;
+import org.wikipedia.page.PageTitle;
+
+import java.io.IOException;
+import java.util.List;
+
+import retrofit2.Call;
+import retrofit2.Response;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+
+public class ReadingListPageInfoClient {
+ @NonNull private MwCachedService<Service> cachedService = new
MwCachedService<>(Service.class);
+
+ public interface Callback {
+ void success(@NonNull Call<MwQueryResponse<QueryResult>> call,
@NonNull List<MwQueryPage> results);
+ void failure(@NonNull Call<MwQueryResponse<QueryResult>> call,
@NonNull Throwable caught);
+ }
+
+ public Call<MwQueryResponse<QueryResult>> request(@NonNull WikiSite wiki,
+ @NonNull List<PageTitle>
titles,
+ @NonNull Callback cb) {
+ return request(cachedService.service(wiki), titles, cb);
+ }
+
+ @VisibleForTesting
+ public Call<MwQueryResponse<QueryResult>> request(@NonNull Service service,
+ @NonNull List<PageTitle>
titles,
+ @NonNull final Callback
cb) {
+ Call<MwQueryResponse<QueryResult>> call =
service.request(TextUtils.join("|", titles), titles.size());
+ call.enqueue(new retrofit2.Callback<MwQueryResponse<QueryResult>>() {
+ @Override public void
onResponse(Call<MwQueryResponse<QueryResult>> call,
+
Response<MwQueryResponse<QueryResult>> response) {
+ if (response.isSuccessful()) {
+ if (response.body().success()) {
+ // noinspection ConstantConditions
+ cb.success(call, response.body().query().pages());
+ } else if (response.body().hasError()) {
+ // noinspection ConstantConditions
+ cb.failure(call, new
MwException(response.body().getError()));
+ } else {
+ cb.failure(call, new IOException("An unknown error
occurred."));
+ }
+
+ } else {
+ cb.failure(call, RetrofitException.httpError(response));
+ }
+ }
+
+ @Override public void onFailure(Call<MwQueryResponse<QueryResult>>
call, Throwable t) {
+ cb.failure(call, t);
+ }
+ });
+ return call;
+ }
+
+ // TODO: Move this intermediate step from the various MwQueryResponse data
clients into MwQueryResponse itself
+ class QueryResult {
+ @SuppressWarnings("unused") @Nullable private List<MwQueryPage> pages;
+
+ @Nullable List<MwQueryPage> pages() {
+ return pages;
+ }
+ }
+
+ @VisibleForTesting interface Service {
+
@GET("w/api.php?action=query&format=json&formatversion=2&prop=pageimages|pageterms"
+ +
"&piprop=thumbnail&pilicense=any&continue=&wbptterms=description&pithumbsize="
+ + Constants.PREFERRED_THUMB_SIZE)
+ Call<MwQueryResponse<QueryResult>> request(@NonNull @Query("titles")
String titles,
+ @Query("pilimit") int
piLimit);
+ }
+}
diff --git
a/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoTask.java
b/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoTask.java
deleted file mode 100644
index 69df8a0..0000000
--- a/app/src/main/java/org/wikipedia/readinglist/ReadingListPageInfoTask.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.wikipedia.readinglist;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.mediawiki.api.json.Api;
-import org.mediawiki.api.json.RequestBuilder;
-import org.wikipedia.dataclient.WikiSite;
-import org.wikipedia.page.PageQueryTask;
-import org.wikipedia.page.PageTitle;
-
-import java.util.List;
-
-public class ReadingListPageInfoTask extends PageQueryTask<Void> {
- private List<PageTitle> titles;
- private final int thumbSize;
- private final int pageCount;
-
- public ReadingListPageInfoTask(Api api, WikiSite wiki, List<PageTitle>
titles, int thumbSize) {
- super(api, wiki, titles);
- this.titles = titles;
- this.thumbSize = thumbSize;
- this.pageCount = titles.size();
- }
-
- @Override
- public void buildQueryParams(RequestBuilder builder) {
- builder.param("prop", "pageimages|pageterms")
- .param("piprop", "thumbnail")
- .param("pilicense", "any")
- .param("pithumbsize", Integer.toString(thumbSize))
- .param("pilimit", Integer.toString(pageCount));
- }
-
- @Override
- public Void processPage(int pageId, PageTitle pageTitle, JSONObject
pageData) throws Throwable {
- for (PageTitle title : titles) {
- if (title.getDisplayText().equals(pageTitle.getDisplayText())) {
- JSONObject thumbnail = pageData.optJSONObject("thumbnail");
- if (thumbnail != null) {
- title.setThumbUrl(thumbnail.optString("source"));
- }
- JSONObject terms = pageData.optJSONObject("terms");
- if (terms != null) {
- JSONArray description = terms.optJSONArray("description");
- if (description != null) {
- title.setDescription(description.optString(0));
- }
- }
- }
- }
- return null;
- }
-}
diff --git a/app/src/main/java/org/wikipedia/util/BatchUtil.java
b/app/src/main/java/org/wikipedia/util/BatchUtil.java
new file mode 100644
index 0000000..3cf92f2
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/util/BatchUtil.java
@@ -0,0 +1,42 @@
+package org.wikipedia.util;
+
+import android.support.annotation.NonNull;
+
+import org.wikipedia.page.PageTitle;
+
+import java.util.List;
+
+import static org.wikipedia.Constants.API_QUERY_MAX_TITLES;
+
+public final class BatchUtil {
+ public static <T> void makeBatches(@NonNull final List<PageTitle> titles,
+ @NonNull Handler<T> handler,
+ @NonNull final Callback<T> callback) {
+ for (int i = 0; i < titles.size(); i += Math.min(API_QUERY_MAX_TITLES,
titles.size() - i)) {
+ handler.handleBatch(titles.subList(i, i +
Math.min(API_QUERY_MAX_TITLES, titles.size() - i)),
+ titles.size(), new Callback<T>() {
+ @Override
+ public void success(@NonNull List<T> results) {
+ callback.success(results);
+ }
+
+ @Override
+ public void failure(@NonNull Throwable caught) {
+ callback.failure(caught);
+ }
+ });
+ }
+ }
+
+ public interface Handler<T> {
+ void handleBatch(@NonNull List<PageTitle> batchTitles, int total,
Callback<T> cb);
+ }
+
+ public interface Callback<T> {
+ void success(@NonNull List<T> results);
+ void failure(@NonNull Throwable caught);
+ }
+
+ private BatchUtil() {
+ }
+}
diff --git
a/app/src/test/java/org/wikipedia/readinglist/ReadingListPageInfoClientTest.java
b/app/src/test/java/org/wikipedia/readinglist/ReadingListPageInfoClientTest.java
new file mode 100644
index 0000000..6d2fdf7
--- /dev/null
+++
b/app/src/test/java/org/wikipedia/readinglist/ReadingListPageInfoClientTest.java
@@ -0,0 +1,100 @@
+package org.wikipedia.readinglist;
+
+import android.support.annotation.NonNull;
+
+import com.google.gson.stream.MalformedJsonException;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.dataclient.mwapi.MwException;
+import org.wikipedia.dataclient.mwapi.MwQueryPage;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.dataclient.okhttp.HttpStatusException;
+import org.wikipedia.page.PageTitle;
+import org.wikipedia.test.MockWebServerTest;
+
+import java.util.Collections;
+import java.util.List;
+
+import retrofit2.Call;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+public class ReadingListPageInfoClientTest extends MockWebServerTest {
+ @NonNull private final ReadingListPageInfoClient subject = new
ReadingListPageInfoClient();
+
+ @Test @SuppressWarnings("checkstyle:magicnumber") public void
testRequestSuccess() throws Throwable {
+ enqueueFromFile("reading_list_page_info.json");
+
+ ReadingListPageInfoClient.Callback cb =
mock(ReadingListPageInfoClient.Callback.class);
+ Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+
+ ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+ verify(cb).success(eq(call), captor.capture());
+
+ List<MwQueryPage> result = captor.getValue();
+ MwQueryPage biden = result.get(0);
+ MwQueryPage obama = result.get(1);
+
+ assertThat(biden.title(), is("Joe Biden"));
+ assertThat(biden.description(), is("47th Vice President of the United
States"));
+ assertThat(biden.thumbUrl(),
is("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Official_portrait_of_Vice_President_Joe_Biden.jpg/255px-Official_portrait_of_Vice_President_Joe_Biden.jpg"));
+
+ assertThat(obama.title(), is("Barack Obama"));
+ assertThat(obama.description(), is("44th President of the United
States of America"));
+ assertThat(obama.thumbUrl(),
is("https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/President_Barack_Obama.jpg/256px-President_Barack_Obama.jpg"));
+ }
+
+ @Test public void testRequestResponseApiError() throws Throwable {
+ enqueueFromFile("api_error.json");
+
+ ReadingListPageInfoClient.Callback cb =
mock(ReadingListPageInfoClient.Callback.class);
+ Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, MwException.class);
+ }
+
+ @Test public void testRequestResponseFailure() throws Throwable {
+ enqueue404();
+
+ ReadingListPageInfoClient.Callback cb =
mock(ReadingListPageInfoClient.Callback.class);
+ Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, HttpStatusException.class);
+ }
+
+ @Test public void testRequestResponseMalformed() throws Throwable {
+ server().enqueue("'");
+
+ ReadingListPageInfoClient.Callback cb =
mock(ReadingListPageInfoClient.Callback.class);
+ Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call =
request(cb);
+
+ server().takeRequest();
+ assertCallbackFailure(call, cb, MalformedJsonException.class);
+ }
+
+ private void assertCallbackFailure(@NonNull
Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>> call,
+ @NonNull
ReadingListPageInfoClient.Callback cb,
+ @NonNull Class<? extends Throwable>
throwable) {
+ //noinspection unchecked
+ verify(cb, never()).success(any(Call.class), any(List.class));
+ verify(cb).failure(eq(call), isA(throwable));
+ }
+
+ private Call<MwQueryResponse<ReadingListPageInfoClient.QueryResult>>
request(@NonNull ReadingListPageInfoClient.Callback cb) {
+ return
subject.request(service(ReadingListPageInfoClient.Service.class),
+ Collections.singletonList(new PageTitle("test",
WikiSite.forLanguageCode("test"))), cb);
+ }
+}
diff --git a/app/src/test/java/org/wikipedia/util/BatchUtilTest.java
b/app/src/test/java/org/wikipedia/util/BatchUtilTest.java
new file mode 100644
index 0000000..5901346
--- /dev/null
+++ b/app/src/test/java/org/wikipedia/util/BatchUtilTest.java
@@ -0,0 +1,52 @@
+package org.wikipedia.util;
+
+import android.support.annotation.NonNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.page.PageTitle;
+import org.wikipedia.test.TestRunner;
+import org.wikipedia.testlib.TestLatch;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(TestRunner.class) public class BatchUtilTest {
+ private ArrayList<PageTitle> titles;
+ private static final int TOTAL = 120;
+
+ @Before public void setUp() throws Throwable {
+ titles = new ArrayList<>();
+ for (int i = 0; i < TOTAL; i++) {
+ titles.add(new PageTitle("foo", WikiSite.forLanguageCode("test")));
+ }
+ }
+
+ @Test @SuppressWarnings("checkstyle:magicnumber") public void
testMwApiBatches() throws Throwable {
+ final TestLatch latch = new TestLatch();
+
+ BatchUtil.makeBatches(titles, new BatchUtil.Handler<Integer>() {
+ private List<Integer> sizes = new ArrayList<>();
+ private int count;
+
+ @Override public void handleBatch(@NonNull List<PageTitle>
batchTitles, int total,
+ BatchUtil.Callback<Integer> cb) {
+ sizes.add(batchTitles.size());
+ count += batchTitles.size();
+
+ if (count == TOTAL) {
+ assertThat(sizes.get(0), is(50));
+ assertThat(sizes.get(1), is(50));
+ assertThat(sizes.get(2), is(20));
+ latch.countDown();
+ }
+ }
+ }, null);
+ latch.await();
+ }
+}
diff --git a/app/src/test/res/raw/reading_list_page_info.json
b/app/src/test/res/raw/reading_list_page_info.json
new file mode 100644
index 0000000..bdde733
--- /dev/null
+++ b/app/src/test/res/raw/reading_list_page_info.json
@@ -0,0 +1,49 @@
+{
+ "batchcomplete": true,
+ "query": {
+ "normalized": [
+ {
+ "fromencoded": false,
+ "from": "Barack_Obama",
+ "to": "Barack Obama"
+ },
+ {
+ "fromencoded": false,
+ "from": "Joe_Biden",
+ "to": "Joe Biden"
+ }
+ ],
+ "pages": [
+ {
+ "pageid": 145422,
+ "ns": 0,
+ "title": "Joe Biden",
+ "thumbnail": {
+ "source":
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Official_portrait_of_Vice_President_Joe_Biden.jpg/255px-Official_portrait_of_Vice_President_Joe_Biden.jpg",
+ "width": 255,
+ "height": 320
+ },
+ "terms": {
+ "description": [
+ "47th Vice President of the United States"
+ ]
+ }
+ },
+ {
+ "pageid": 534366,
+ "ns": 0,
+ "title": "Barack Obama",
+ "thumbnail": {
+ "source":
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/President_Barack_Obama.jpg/256px-President_Barack_Obama.jpg",
+ "width": 256,
+ "height": 320
+ },
+ "terms": {
+ "description": [
+ "44th President of the United States of America"
+ ]
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/337508
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Icb66a97590323351992b18aa713ec30a8f03578f
Gerrit-PatchSet: 5
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Mholloway <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Dbrant <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: Niedzielski <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits