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

Reply via email to