mobile/android/base/tests/SessionTest.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 package org.mozilla.gecko.tests;
     3 import java.io.File;
     4 import java.io.FileReader;
     5 import java.io.FileWriter;
     6 import java.io.IOException;
     8 import org.json.JSONArray;
     9 import org.json.JSONException;
    10 import org.json.JSONObject;
    11 import org.mozilla.gecko.Actions;
    12 import org.mozilla.gecko.Assert;
    13 import org.mozilla.gecko.FennecMochitestAssert;
    15 public abstract class SessionTest extends BaseTest {
    16     protected Navigation mNavigation;
    18     @Override
    19     public void setUp() throws Exception {
    20         super.setUp();
    22         mNavigation = new Navigation(mDevice);
    23     }
    25     /**
    26      * A generic session object representing a collection of items that has a
    27      * selected index.
    28      */
    29     protected abstract class SessionObject<T> {
    30         private final int mIndex;
    31         private final T[] mItems;
    33         public SessionObject(int index, T... items) {
    34             mIndex = index;
    35             mItems = items;
    36         }
    38         public int getIndex() {
    39             return mIndex;
    40         }
    42         public T[] getItems() {
    43             return mItems;
    44         }
    45     }
    47     protected class PageInfo {
    48         private String url;
    49         private String title;
    51         public PageInfo(String key) {
    52             if (key.startsWith("about:")) {
    53                 url = key;
    54             } else {
    55                 url = getPage(key);
    56             }
    57             title = key;
    58         }
    59     }
    61     protected class SessionTab extends SessionObject<PageInfo> {
    62         public SessionTab(int index, PageInfo... items) {
    63             super(index, items);
    64         }
    65     }
    67     protected class Session extends SessionObject<SessionTab> {
    68         public Session(int index, SessionTab... items) {
    69             super(index, items);
    70         }
    71     }
    73     /**
    74      * Walker for visiting items in a browser-like navigation order.
    75      */
    76     protected abstract class NavigationWalker<T> {
    77         private final T[] mItems;
    78         private final int mIndex;
    80         public NavigationWalker(SessionObject<T> obj) {
    81             mItems = obj.getItems();
    82             mIndex = obj.getIndex();
    83         }
    85         /**
    86          * Walks over the list of items, calling the onItem() callback for each.
    87          *
    88          * The selected item is the first item visited. Each item after the
    89          * selected item is then visited in ascending index order. Finally, the
    90          * list is iterated in reverse, and each item before the selected item
    91          * is visited in descending index order.
    92          */
    93         public void walk() {
    94             onItem(mItems[mIndex], mIndex);
    95             for (int i = mIndex + 1; i < mItems.length; i++) {
    96                 goForward();
    97                 onItem(mItems[i], i);
    98             }
    99             if (mIndex > 0) {
   100                 for (int i = mItems.length - 2; i >= 0; i--) {
   101                     goBack();
   102                     if (i < mIndex) {
   103                         onItem(mItems[i], i);
   104                     }
   105                 }
   106             }
   107         }
   109         /**
   110          * Callback when an item is visited during a walk.
   111          *
   112          * Only one callback is executed per item.
   113          */
   114         public abstract void onItem(T item, int currentIndex);
   116         /**
   117          * Callback executed for each back step of the walk.
   118          */
   119         public void goBack() {}
   121         /**
   122          * Callback executed for each forward step of the walk.
   123          */
   124         public void goForward() {}
   125     }
   127     /**
   128      * Loads a set of tabs in the browser specified by the given session.
   129      *
   130      * @param session Session to load
   131      */
   132     protected void loadSessionTabs(Session session) {
   133         // Verify initial about:home tab
   134         verifyTabCount(1);
   135         verifyUrl("about:home");
   137         SessionTab[] tabs = session.getItems();
   138         for (int i = 0; i < tabs.length; i++) {
   139             final SessionTab tab = tabs[i];
   140             final PageInfo[] pages = tab.getItems();
   142             // New tabs always start with about:home, so make sure about:home
   143             // is always the first entry.
   144             mAsserter.is(pages[0].url, "about:home", "first page in tab is about:home");
   146             // If this is the first tab, the tab already exists, so no need to
   147             // create a new one. Otherwise, create a new tab if we're loading
   148             // the first the first page in the set.
   149             if (i > 0) {
   150                 addTab();
   151             }
   153             for (int j = 1; j < pages.length; j++) {
   154                 Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow");
   156                 loadUrl(pages[j].url);
   158                 pageShowExpecter.blockForEvent();
   159                 pageShowExpecter.unregisterListener();
   160             }
   162             final int index = tab.getIndex();
   163             for (int j = pages.length - 1; j > index; j--) {
   164                 mNavigation.back();
   165             }
   166         }
   168         selectTabAt(session.getIndex());
   169     }
   171     /**
   172      * Verifies that the set of open tabs matches the given session.
   173      *
   174      * @param session Session to verify
   175      */
   176     protected void verifySessionTabs(Session session) {
   177         verifyTabCount(session.getItems().length);
   179         (new NavigationWalker<SessionTab>(session) {
   180             boolean mFirstTabVisited;
   182             @Override
   183             public void onItem(SessionTab tab, int currentIndex) {
   184                 // The first tab to check should already be selected at startup
   185                 if (mFirstTabVisited) {
   186                     selectTabAt(currentIndex);
   187                 } else {
   188                     mFirstTabVisited = true;
   189                 }
   191                 (new NavigationWalker<PageInfo>(tab) {
   192                     @Override
   193                     public void onItem(PageInfo page, int currentIndex) {
   194                         if (page.url.equals("about:home")) {
   195                             waitForText("Enter Search or Address");
   196                             verifyUrl(page.url);
   197                         } else {
   198                             waitForText(page.title);
   199                             verifyPageTitle(page.title);
   200                         }
   201                     }
   203                     @Override
   204                     public void goBack() {
   205                         mNavigation.back();
   206                     }
   208                     @Override
   209                     public void goForward() {
   210                         mNavigation.forward();
   211                     }
   212                 }).walk();
   213             }
   214         }).walk();
   215     }
   217     /**
   218      * Gets session restore JSON corresponding to the open session.
   219      *
   220      * The JSON format follows the format used in Gecko for session restore and
   221      * should be interchangeable with the Gecko's generated sessionstore.js.
   222      *
   223      * @param session Session to serialize
   224      * @return JSON string of session
   225      */
   226     protected String buildSessionJSON(Session session) {
   227         final SessionTab[] sessionTabs = session.getItems();
   228         String sessionString = null;
   230         try {
   231             final JSONArray tabs = new JSONArray();
   233             for (int i = 0; i < sessionTabs.length; i++) {
   234                 final JSONObject tab = new JSONObject();
   235                 final JSONArray entries = new JSONArray();
   236                 final SessionTab sessionTab = sessionTabs[i];
   237                 final PageInfo[] pages = sessionTab.getItems();
   239                 for (int j = 0; j < pages.length; j++) {
   240                     final PageInfo page = pages[j];
   241                     final JSONObject entry = new JSONObject();
   242                     entry.put("url", page.url);
   243                     entry.put("title", page.title);
   244                     entries.put(entry);
   245                 }
   247                 tab.put("entries", entries);
   248                 tab.put("index", sessionTab.getIndex() + 1);
   249                 tabs.put(tab);
   250             }
   252             JSONObject window = new JSONObject();
   253             window.put("tabs", tabs);
   254             window.put("selected", session.getIndex() + 1);
   255             sessionString = new JSONObject().put("windows", new JSONArray().put(window)).toString();
   256         } catch (JSONException e) {
   257             mAsserter.ok(false, "JSON exception", getStackTraceString(e));
   258         }
   260         return sessionString;
   261     }
   263     /**
   264      * @see SessionTest#verifySessionJSON(Session, String, Assert)
   265      */
   266     protected void verifySessionJSON(Session session, String sessionString) {
   267         verifySessionJSON(session, sessionString, mAsserter);
   268     }
   270     /**
   271      * Verifies a session JSON string against the given session.
   272      *
   273      * @param session       Session to verify against
   274      * @param sessionString JSON string to verify
   275      * @param asserter      Assert class to use during verification
   276      */
   277     protected void verifySessionJSON(Session session, String sessionString, Assert asserter) {
   278         final SessionTab[] sessionTabs = session.getItems();
   280         try {
   281             final JSONObject window = new JSONObject(sessionString).getJSONArray("windows").getJSONObject(0);
   282             final JSONArray tabs = window.getJSONArray("tabs");
   283             final int optSelected = window.optInt("selected", -1);
   285             asserter.is(optSelected, session.getIndex() + 1, "selected tab matches");
   287             for (int i = 0; i < tabs.length(); i++) {
   288                 final JSONObject tab = tabs.getJSONObject(i);
   289                 final int index = tab.getInt("index");
   290                 final JSONArray entries = tab.getJSONArray("entries");
   291                 final SessionTab sessionTab = sessionTabs[i];
   292                 final PageInfo[] pages = sessionTab.getItems();
   294                 asserter.is(index, sessionTab.getIndex() + 1, "selected page index matches");
   296                 for (int j = 0; j < entries.length(); j++) {
   297                     final JSONObject entry = entries.getJSONObject(j);
   298                     final String url = entry.getString("url");
   299                     final String title = entry.optString("title");
   300                     final PageInfo page = pages[j];
   302                     asserter.is(url, page.url, "URL in JSON matches session URL");
   303                     if (!page.url.startsWith("about:")) {
   304                         asserter.is(title, page.title, "title in JSON matches session title");
   305                     }
   306                 }
   307             }
   308         } catch (JSONException e) {
   309             asserter.ok(false, "JSON exception", getStackTraceString(e));
   310         }
   311     }
   313     /**
   314      * Exception thrown by NonFatalAsserter for assertion failures.
   315      */
   316     public static class AssertException extends RuntimeException {
   317         public AssertException(String msg) {
   318             super(msg);
   319         }
   320     }
   322     /**
   323      * Asserter that throws an AssertException on failure instead of aborting
   324      * the test.
   325      *
   326      * This can be used in methods called via waitForCondition() where an assertion
   327      * might not immediately succeed.
   328      */
   329     public class NonFatalAsserter extends FennecMochitestAssert {
   330         @Override
   331         public void ok(boolean condition, String name, String diag) {
   332             if (!condition) {
   333                 String details = (diag == null ? "" : " | " + diag);
   334                 throw new AssertException("Assertion failed: " + name + details);
   335             }
   336             mAsserter.ok(condition, name, diag);
   337         }
   338     }
   340     /**
   341      * Gets a URL for a dynamically-generated page.
   342      *
   343      * The page will have a URL unique to the given ID, and the page's title
   344      * will match the given ID.
   345      *
   346      * @param id ID used to generate page URL
   347      * @return URL of the page
   348      */
   349     protected String getPage(String id) {
   350         return getAbsoluteUrl("/robocop/robocop_dynamic.sjs?id=" + id);
   351     }
   353     protected String readProfileFile(String filename) {
   354         try {
   355             return readFile(new File(mProfile, filename));
   356         } catch (IOException e) {
   357             mAsserter.ok(false, "Error reading" + filename, getStackTraceString(e));
   358         }
   359         return null;
   360     }
   362     protected void writeProfileFile(String filename, String data) {
   363         try {
   364             writeFile(new File(mProfile, filename), data);
   365         } catch (IOException e) {
   366             mAsserter.ok(false, "Error writing to " + filename, getStackTraceString(e));
   367         }
   368     }
   370     private String readFile(File target) throws IOException {
   371         if (!target.exists()) {
   372             return null;
   373         }
   375         FileReader fr = new FileReader(target);
   376         try {
   377             StringBuffer sb = new StringBuffer();
   378             char[] buf = new char[8192];
   379             int read = fr.read(buf);
   380             while (read >= 0) {
   381                 sb.append(buf, 0, read);
   382                 read = fr.read(buf);
   383             }
   384             return sb.toString();
   385         } finally {
   386             fr.close();
   387         }
   388     }
   390     private void writeFile(File target, String data) throws IOException {
   391         FileWriter writer = new FileWriter(target);
   392         try {
   393             writer.write(data);
   394         } finally {
   395             writer.close();
   396         }
   397     }
   398 }

mercurial