Chromium Code Reviews| Index: chrome/android/javatests/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java |
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..998fd1b327694840e1458516b4a94bebcb195809 |
| --- /dev/null |
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java |
| @@ -0,0 +1,362 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.omaha; |
| + |
| +import android.test.InstrumentationTestCase; |
| +import android.test.suitebuilder.annotation.SmallTest; |
| +import android.util.Xml; |
| + |
| +import org.chromium.base.test.util.Feature; |
| +import org.xmlpull.v1.XmlSerializer; |
| + |
| +import java.io.IOException; |
| +import java.io.StringWriter; |
| + |
| +/** |
| + * Unit tests for the Omaha ResponseParser. |
| + */ |
| +public class ResponseParserTest extends InstrumentationTestCase { |
| + // Note that the Omaha server appends "/" to the end of the URL codebase. |
| + private static final String STRIPPED_URL = |
| + "https://play.google.com/store/apps/details?id=com.google.android.apps.chrome"; |
| + private static final String URL = STRIPPED_URL + "/"; |
| + private static final String NEXT_VERSION = "1.2.3.4"; |
| + |
| + private static final String APP_STATUS_OK = "ok"; |
| + private static final String APP_STATUS_RESTRICTED = "restricted"; |
| + private static final String APP_STATUS_ERROR = "error-whatever-else"; |
| + |
| + private static final String UPDATE_STATUS_OK = "ok"; |
| + private static final String UPDATE_STATUS_NOUPDATE = "noupdate"; |
| + private static final String UPDATE_STATUS_ERROR = "error-osnotsupported"; |
| + private static final String UPDATE_STATUS_WTF = "omgwtfbbq"; |
| + |
| + /** |
| + * Create XML for testing. |
| + * @param xmlProtocol Version number of the protocol. Expected to be "3.0" for valid XML. |
| + * @param elapsedSeconds Number of seconds since server midnight. |
| + * @param appStatus Status to use for the <app> element. |
| + * @param addInstall Whether or not to add an install event. |
| + * @param addPing Whether or not to add a ping event. |
| + * @param updateStatus Status to use for the <updatecheck> element. |
| + * @return The completed XML. |
| + */ |
| + private static String createTestXML(String xmlProtocol, String elapsedSeconds, |
| + String appStatus, boolean addInstall, boolean addPing, String updateStatus, |
| + String updateUrl) { |
| + StringWriter writer = new StringWriter(); |
| + try { |
| + XmlSerializer serializer = Xml.newSerializer(); |
| + serializer.setOutput(writer); |
| + serializer.startDocument("UTF-8", true); |
| + |
| + // Set up <response ...> |
| + serializer.startTag(null, "response"); |
| + serializer.attribute(null, "server", "prod"); |
| + if (xmlProtocol != null) { |
| + serializer.attribute(null, "protocol", xmlProtocol); |
| + } |
| + |
| + // Create <daystart> element. |
| + if (elapsedSeconds != null) { |
| + serializer.startTag(null, "daystart"); |
| + serializer.attribute(null, "elapsed_seconds", elapsedSeconds); |
| + serializer.endTag(null, "daystart"); |
| + } |
| + |
| + // Create <app> element with unused attribute. |
| + serializer.startTag(null, "app"); |
| + serializer.attribute(null, "appid", "{APP_ID}"); |
| + serializer.attribute(null, "status", appStatus); |
| + serializer.attribute(null, "unused", "attribute"); |
| + |
| + if (addInstall) { |
| + serializer.startTag(null, "event"); |
| + serializer.attribute(null, "status", "ok"); |
| + serializer.endTag(null, "event"); |
| + } |
| + |
| + if (addPing) { |
| + serializer.startTag(null, "ping"); |
| + serializer.attribute(null, "status", "ok"); |
| + serializer.endTag(null, "ping"); |
| + } |
| + |
| + if (updateStatus != null) { |
| + serializer.startTag(null, "updatecheck"); |
| + serializer.attribute(null, "status", updateStatus); |
| + if (UPDATE_STATUS_OK.equals(updateStatus)) { |
| + createUpdateXML(serializer, updateUrl); |
| + } |
| + serializer.endTag(null, "updatecheck"); |
| + } |
| + serializer.endTag(null, "app"); |
| + |
| + // Create extraneous tag. |
| + serializer.startTag(null, "extraneous"); |
| + serializer.attribute(null, "useless", "yes"); |
| + serializer.endTag(null, "extraneous"); |
| + |
| + serializer.endTag(null, "response"); |
| + serializer.endDocument(); |
| + } catch (IOException e) { |
| + fail("Caught an IOException creating the XML: " + e); |
| + } catch (IllegalArgumentException e) { |
| + fail("Caught an IllegalArgumentException creating the XML: " + e); |
| + } catch (IllegalStateException e) { |
| + fail("Caught an IllegalStateException creating the XML: " + e); |
| + } |
| + |
| + return writer.toString(); |
| + } |
| + |
| + private static void createUpdateXML(XmlSerializer serializer, String updateUrl) |
| + throws IllegalArgumentException, IllegalStateException, IOException { |
|
nyquist
2014/01/23 00:54:02
Both IllegalXxxException are unchecked right? So t
gone
2014/01/24 07:43:12
Done.
|
| + // End result should look something like: |
| + // <updatecheck status="ok"> |
| + // <urls> |
| + // <url codebase="URL" /> |
| + // </urls> |
| + // <manifest garbage="attribute" version="NEXT_VERSION"> |
| + // <packages> |
| + // <package hash="0" name="dummy.apk" required="true" size="0" /> |
| + // </packages> |
| + // <actions> |
| + // <action event="install" run="dummy.apk" /> |
| + // <action event="postinstall" /> |
| + // </actions> |
| + // </manifest> |
| + // <better be="ignored" /> |
| + //</updatecheck> |
| + |
| + // Create <urls> and its descendants. |
| + serializer.startTag(null, "urls"); |
| + if (updateUrl != null) { |
| + serializer.startTag(null, "url"); |
| + serializer.attribute(null, "codebase", updateUrl); |
| + serializer.endTag(null, "url"); |
| + } |
| + serializer.endTag(null, "urls"); |
| + |
| + // Create <manifest> and its descendants. |
| + serializer.startTag(null, "manifest"); |
| + serializer.attribute(null, "garbage", "attribute"); |
| + serializer.attribute(null, "version", NEXT_VERSION); |
| + |
| + // Create <packages> and its children. |
| + serializer.startTag(null, "packages"); |
| + serializer.startTag(null, "package"); |
| + serializer.attribute(null, "hash", "0"); |
| + serializer.attribute(null, "name", "dummy.apk"); |
| + serializer.attribute(null, "required", "true"); |
| + serializer.attribute(null, "size", "0"); |
| + serializer.endTag(null, "package"); |
| + serializer.endTag(null, "packages"); |
| + |
| + // Create <actions> and its children. |
| + serializer.startTag(null, "actions"); |
| + serializer.startTag(null, "action"); |
| + serializer.attribute(null, "event", "install"); |
| + serializer.attribute(null, "run", "dummy.apk"); |
| + serializer.endTag(null, "action"); |
| + |
| + serializer.startTag(null, "action"); |
| + serializer.attribute(null, "event", "postinstall"); |
| + serializer.endTag(null, "action"); |
| + serializer.endTag(null, "actions"); |
| + serializer.endTag(null, "manifest"); |
| + |
| + // Create a dummy element for testing to make sure it's ignored. |
| + serializer.startTag(null, "dummy"); |
| + serializer.attribute(null, "hopefully", "ignored"); |
| + serializer.endTag(null, "dummy"); |
| + } |
| + |
| + /** |
| + * Runs a test that is expected to pass. |
| + * @param appStatus Status to use for the <app> element. |
| + * @param addInstall Whether or not to add an install event. |
| + * @param addPing Whether or not to add a ping. |
| + * @param updateStatus Status to use for the <updatecheck> element. |
| + * @throws RequestFailureException Thrown if the test fails. |
| + */ |
| + private static void runSuccessTest(String appStatus, boolean addInstall, boolean addPing, |
| + String updateStatus) throws RequestFailureException { |
| + String xml = |
| + createTestXML("3.0", "12345", appStatus, addInstall, addPing, updateStatus, URL); |
| + ResponseParser parser = |
| + new ResponseParser(true, "{APP_ID}", addInstall, addPing, updateStatus != null); |
| + parser.parseResponse(xml); |
| + |
| + assertEquals("elapsed_seconds doesn't match.", 12345, parser.getDaystartSeconds()); |
| + assertEquals("<app> status doesn't match.", appStatus, parser.getAppStatus()); |
| + assertEquals("<updatecheck> status doesn't match.", updateStatus, parser.getUpdateStatus()); |
| + if (UPDATE_STATUS_OK.equals(updateStatus)) { |
| + assertEquals("Version number doesn't match.", "1.2.3.4", parser.getNewVersion()); |
| + assertEquals("Market URL doesn't match.", STRIPPED_URL, parser.getURL()); |
| + } else { |
| + assertEquals("Version number doesn't match.", null, parser.getNewVersion()); |
| + assertEquals("Market URL doesn't match.", null, parser.getURL()); |
| + } |
| + } |
| + |
| + /** |
| + * Runs a test that is expected to fail in a particular way. |
| + * @param xml XML to parse. |
| + * @param expectedErrorCode Expected error code. |
| + * @param expectInstall Whether or not the parser should expect an install event. |
| + * @param expectPing Whether or not the parser should expect a ping element. |
| + * @param expectUpdate Whether or not the parser should expect an update check. |
| + */ |
| + private static void runFailureTest(String xml, int expectedErrorCode, |
| + boolean expectInstall, boolean expectPing, boolean expectUpdate) { |
| + ResponseParser parser = |
| + new ResponseParser(true, "{APP_ID}", expectInstall, expectPing, expectUpdate); |
| + |
| + try { |
| + parser.parseResponse(xml); |
| + } catch (RequestFailureException e) { |
| + assertEquals("Incorrect error code received.", expectedErrorCode, e.errorCode); |
| + return; |
| + } |
| + |
| + fail("Failed to throw RequestFailureException for bad XML."); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidAllTypes() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, true, true, UPDATE_STATUS_OK); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidNoInstall() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, false, true, UPDATE_STATUS_OK); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidNoPing() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, true, false, UPDATE_STATUS_OK); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidNoUpdatecheck() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, true, true, null); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidUpdatecheckNoUpdate() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, false, false, UPDATE_STATUS_NOUPDATE); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidUpdatecheckError() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, false, false, UPDATE_STATUS_ERROR); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidUpdatecheckUnknown() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_OK, false, false, UPDATE_STATUS_WTF); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testValidAppStatusRestricted() throws RequestFailureException { |
| + runSuccessTest(APP_STATUS_RESTRICTED, false, false, null); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testFailBogusResponse() { |
| + String xml = "Bogus"; |
| + runFailureTest(xml, RequestFailureException.ERROR_MALFORMED_XML, false, false, false); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testBadResponseProtocol() { |
| + String xml = |
| + createTestXML("2.0", "12345", APP_STATUS_OK, false, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_RESPONSE, false, false, false); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testFailMissingDaystart() { |
| + String xml = |
| + createTestXML("3.0", null, APP_STATUS_OK, false, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_DAYSTART, false, false, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagMissingUpdatecheck() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, true, false, null, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_UPDATECHECK, true, false, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagUnexpectedUpdatecheck() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, true, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_UPDATECHECK, true, false, false); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagMissingPing() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, false, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_PING, false, true, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagUnexpectedPing() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, false, true, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_PING, false, false, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagMissingInstall() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, false, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_EVENT, true, false, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagUnexpectedInstall() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_OK, true, false, UPDATE_STATUS_OK, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_EVENT, false, false, true); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testAppTagStatusError() { |
| + String xml = |
| + createTestXML("3.0", "12345", APP_STATUS_ERROR, false, false, null, URL); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_APP, false, false, false); |
| + } |
| + |
| + @SmallTest |
| + @Feature({"Omaha"}) |
| + public void testUpdatecheckMissingUrl() { |
| + String xml = createTestXML( |
| + "3.0", "12345", APP_STATUS_OK, false, false, UPDATE_STATUS_OK, null); |
| + runFailureTest(xml, RequestFailureException.ERROR_PARSE_URLS, false, false, true); |
| + } |
| +} |