chromium/chrome/android/junit/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java

// Copyright 2015 The Chromium Authors
// 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 static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;

import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.omaha.MockRequestGenerator.DeviceType;
import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
import org.chromium.chrome.browser.uid.SettingsSecureBasedIdentificationGenerator;
import org.chromium.chrome.browser.uid.UniqueIdentificationGenerator;
import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory;
import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
import org.chromium.components.signin.identitymanager.IdentityManager;

/** Unit tests for the RequestGenerator class. */
@RunWith(BaseRobolectricTestRunner.class)
@Batch(Batch.UNIT_TESTS)
@Config(manifest = Config.NONE)
public class RequestGeneratorTest {
    private static final String INSTALL_SOURCE = "install_source";

    @Rule
    public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();

    @Test
    @Feature({"Omaha"})
    public void testInstallAgeNewInstallation() {
        long currentTimestamp = 201207310000L;
        long installTimestamp = 198401160000L;
        boolean installing = true;
        long expectedAge = RequestGenerator.INSTALL_AGE_IMMEDIATELY_AFTER_INSTALLING;
        checkInstallAge(currentTimestamp, installTimestamp, installing, expectedAge);
    }

    @Test
    @Feature({"Omaha"})
    public void testInstallAge() {
        long currentTimestamp = 201207310000L;
        long installTimestamp = 198401160000L;
        boolean installing = false;
        long expectedAge = 32;
        checkInstallAge(currentTimestamp, installTimestamp, installing, expectedAge);
    }

    /** Checks whether the install age function is behaving according to spec. */
    void checkInstallAge(
            long currentTimestamp, long installTimestamp, boolean installing, long expectedAge) {
        long actualAge =
                RequestGenerator.installAge(currentTimestamp, installTimestamp, installing);
        Assert.assertEquals("Install ages differed.", expectedAge, actualAge);
    }

    @Test
    @Feature({"Omaha"})
    public void testConstructorRegistersIdentificationGenerator() {
        // First clear the current set of generators.
        UniqueIdentificationGeneratorFactory.clearGeneratorMapForTest();

        // Creating a RequestGenerator should register the identification generator.
        new MockRequestGenerator(DeviceType.HANDSET);

        // Verify the identification generator exists and is of the correct type.
        UniqueIdentificationGenerator instance =
                UniqueIdentificationGeneratorFactory.getInstance(
                        SettingsSecureBasedIdentificationGenerator.GENERATOR_ID);
        Assert.assertTrue(instance instanceof SettingsSecureBasedIdentificationGenerator);
    }

    @Test
    @Feature({"Omaha"})
    public void testHandsetXMLCreationWithInstall() {
        createAndCheckXML(DeviceType.HANDSET, true);
    }

    @Test
    @Feature({"Omaha"})
    public void testHandsetXMLCreationWithoutInstall() {
        createAndCheckXML(DeviceType.HANDSET, false);
    }

    @Test
    @Feature({"Omaha"})
    public void testTabletXMLCreationWithInstall() {
        createAndCheckXML(DeviceType.TABLET, true);
    }

    @Test
    @Feature({"Omaha"})
    public void testTabletXMLCreationWithoutInstall() {
        createAndCheckXML(DeviceType.TABLET, false);
    }

    /** Checks that the XML is being created properly. */
    private RequestGenerator createAndCheckXML(DeviceType deviceType, boolean sendInstallEvent) {
        IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
        when(IdentityServicesProvider.get().getIdentityManager(any()))
                .thenReturn(mock(IdentityManager.class));
        when(IdentityServicesProvider.get().getIdentityManager(any()).hasPrimaryAccount(anyInt()))
                .thenReturn(true);

        String sessionId = "random_session_id";
        String requestId = "random_request_id";
        String version = "1.2.3.4";
        long installAge = 42;
        int dateLastActive = 4088;

        MockRequestGenerator generator = new MockRequestGenerator(deviceType);

        String xml = null;
        try {
            RequestData data = new RequestData(sendInstallEvent, 0, requestId, INSTALL_SOURCE);
            xml = generator.generateXML(sessionId, version, installAge, dateLastActive, data);
        } catch (RequestFailureException e) {
            Assert.fail("XML generation failed.");
        }

        checkForAttributeAndValue(xml, "request", "sessionid", "{" + sessionId + "}");
        checkForAttributeAndValue(xml, "request", "requestid", "{" + requestId + "}");
        checkForAttributeAndValue(xml, "request", "installsource", INSTALL_SOURCE);

        checkForAttributeAndValue(xml, "app", "version", version);
        checkForAttributeAndValue(xml, "app", "lang", generator.getLanguage());
        checkForAttributeAndValue(xml, "app", "brand", generator.getBrand());
        checkForAttributeAndValue(xml, "app", "client", generator.getClient());
        checkForAttributeAndValue(xml, "app", "appid", generator.getAppId());
        checkForAttributeAndValue(xml, "app", "installage", String.valueOf(installAge));
        checkForAttributeAndValue(xml, "app", "ap", generator.getAdditionalParameters());

        if (sendInstallEvent) {
            checkForAttributeAndValue(xml, "event", "eventtype", "2");
            checkForAttributeAndValue(xml, "event", "eventresult", "1");
            Assert.assertFalse(
                    "Ping and install event are mutually exclusive", checkForTag(xml, "ping"));
            Assert.assertFalse(
                    "Update check and install event are mutually exclusive",
                    checkForTag(xml, "updatecheck"));
        } else {
            Assert.assertFalse(
                    "Update check and install event are mutually exclusive",
                    checkForTag(xml, "event"));
            checkForAttributeAndValue(xml, "ping", "active", "1");
            checkForAttributeAndValue(xml, "ping", "rd", String.valueOf(dateLastActive));
            checkForAttributeAndValue(xml, "ping", "ad", String.valueOf(dateLastActive));
            Assert.assertTrue(
                    "Update check and install event are mutually exclusive",
                    checkForTag(xml, "updatecheck"));
        }

        return generator;
    }

    private boolean checkForTag(String xml, String tag) {
        return new AttributeFinder(xml, tag, null).isTagFound();
    }

    private void checkForAttributeAndValue(
            String xml, String tag, String attribute, String expectedValue) {
        // Check that the attribute exists for the tag and that the value matches.
        AttributeFinder finder = new AttributeFinder(xml, tag, attribute);
        Assert.assertTrue("Couldn't find tag '" + tag + "'", finder.isTagFound());
        Assert.assertEquals(
                "Bad value found for tag '" + tag + "' and attribute '" + attribute + "'",
                expectedValue,
                finder.getValue());
    }
}