// Copyright 2018 The Feed Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.android.libraries.feed.feedrequestmanager;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.LiteProtoTruth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.util.Base64;
import com.google.android.libraries.feed.api.host.config.ApplicationInfo;
import com.google.android.libraries.feed.api.host.config.Configuration;
import com.google.android.libraries.feed.api.host.config.Configuration.ConfigKey;
import com.google.android.libraries.feed.api.host.logging.RequestReason;
import com.google.android.libraries.feed.api.host.network.HttpRequest;
import com.google.android.libraries.feed.api.host.network.HttpRequest.HttpMethod;
import com.google.android.libraries.feed.api.host.network.HttpResponse;
import com.google.android.libraries.feed.api.host.scheduler.SchedulerApi;
import com.google.android.libraries.feed.api.host.stream.TooltipInfo.FeatureName;
import com.google.android.libraries.feed.api.internal.common.DismissActionWithSemanticProperties;
import com.google.android.libraries.feed.common.Result;
import com.google.android.libraries.feed.common.concurrent.testing.FakeMainThreadRunner;
import com.google.android.libraries.feed.common.concurrent.testing.FakeTaskQueue;
import com.google.android.libraries.feed.common.concurrent.testing.FakeThreadUtils;
import com.google.android.libraries.feed.common.locale.LocaleUtils;
import com.google.android.libraries.feed.common.protoextensions.FeedExtensionRegistry;
import com.google.android.libraries.feed.common.testing.RequiredConsumer;
import com.google.android.libraries.feed.common.time.TimingUtils;
import com.google.android.libraries.feed.common.time.testing.FakeClock;
import com.google.android.libraries.feed.testing.actionmanager.FakeActionReader;
import com.google.android.libraries.feed.testing.host.logging.FakeBasicLoggingApi;
import com.google.android.libraries.feed.testing.host.stream.FakeTooltipSupportedApi;
import com.google.android.libraries.feed.testing.network.FakeNetworkClient;
import com.google.android.libraries.feed.testing.protocoladapter.FakeProtocolAdapter;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.search.now.feed.client.StreamDataProto.StreamDataOperation;
import com.google.search.now.feed.client.StreamDataProto.StreamToken;
import com.google.search.now.wire.feed.ActionTypeProto.ActionType;
import com.google.search.now.wire.feed.CapabilityProto.Capability;
import com.google.search.now.wire.feed.ClientInfoProto.ClientInfo;
import com.google.search.now.wire.feed.ClientInfoProto.ClientInfo.AppType;
import com.google.search.now.wire.feed.ClientInfoProto.ClientInfo.PlatformType;
import com.google.search.now.wire.feed.ConsistencyTokenProto.ConsistencyToken;
import com.google.search.now.wire.feed.ContentIdProto.ContentId;
import com.google.search.now.wire.feed.DisplayInfoProto.DisplayInfo;
import com.google.search.now.wire.feed.FeedActionQueryDataProto.Action;
import com.google.search.now.wire.feed.FeedActionQueryDataProto.FeedActionQueryData;
import com.google.search.now.wire.feed.FeedActionQueryDataProto.FeedActionQueryDataItem;
import com.google.search.now.wire.feed.FeedQueryProto.FeedQuery;
import com.google.search.now.wire.feed.FeedRequestProto.FeedRequest;
import com.google.search.now.wire.feed.RequestProto.Request;
import com.google.search.now.wire.feed.RequestProto.Request.RequestVersion;
import com.google.search.now.wire.feed.ResponseProto.Response;
import com.google.search.now.wire.feed.SemanticPropertiesProto.SemanticProperties;
import com.google.search.now.wire.feed.VersionProto.Version;
import com.google.search.now.wire.feed.VersionProto.Version.Architecture;
import com.google.search.now.wire.feed.VersionProto.Version.BuildType;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;

/** Test of the {@link FeedRequestManagerImpl} class. */
@RunWith(RobolectricTestRunner.class)
public class FeedRequestManagerImplTest {

  private static final int NOT_FOUND = 404;
  private static final String TABLE = "table";
  private static final String TABLE_2 = "table2";
  private static final String CONTENT_DOMAIN = "contentDomain";
  private static final String CONTENT_DOMAIN_2 = "contentDomain2";
  public static final long ID = 42;
  private static final long ID_2 = 2;
  private static final String APP_VERSION_STRING = "5.7";

  private final FakeClock fakeClock = new FakeClock();
  private final TimingUtils timingUtils = new TimingUtils();
  private final Configuration configuration = new Configuration.Builder().build();

  @Mock private SchedulerApi scheduler;
  @Mock private ApplicationInfo applicationInfo;

  private Context context;
  private ExtensionRegistryLite registry;
  private FeedRequestManagerImpl requestManager;
  private FakeActionReader fakeActionReader;
  private FakeMainThreadRunner fakeMainThreadRunner;
  private FakeProtocolAdapter fakeProtocolAdapter;
  private FakeThreadUtils fakeThreadUtils;
  private FakeTaskQueue fakeTaskQueue;
  private FakeBasicLoggingApi fakeBasicLoggingApi;
  private FakeNetworkClient fakeNetworkClient;
  private FakeTooltipSupportedApi fakeTooltipSupportedApi;
  private RequiredConsumer<Result<List<StreamDataOperation>>> consumer;
  private Result<List<StreamDataOperation>> consumedResult = Result.failure();
  private HttpResponse failingResponse;

  @Before
  public void setUp() throws Exception {
    initMocks(this);
    context = Robolectric.buildActivity(Activity.class).get();
    context.getResources().getConfiguration().locale = Locale.US;
    FeedExtensionRegistry feedExtensionRegistry = new FeedExtensionRegistry(ArrayList::new);
    registry = ExtensionRegistryLite.newInstance();
    registry.add(FeedRequest.feedRequest);
    fakeActionReader = new FakeActionReader();
    fakeProtocolAdapter = new FakeProtocolAdapter();
    fakeBasicLoggingApi = new FakeBasicLoggingApi();
    fakeThreadUtils = FakeThreadUtils.withThreadChecks();
    fakeMainThreadRunner =
        FakeMainThreadRunner.runTasksImmediatelyWithThreadChecks(fakeThreadUtils);
    fakeNetworkClient = new FakeNetworkClient(fakeThreadUtils);
    fakeNetworkClient.setDefaultResponse(
        createHttpResponse(/* responseCode= */ 200, Response.getDefaultInstance()));
    fakeTaskQueue = new FakeTaskQueue(fakeClock, fakeThreadUtils);
    fakeTaskQueue.initialize(() -> {});
    fakeTooltipSupportedApi = new FakeTooltipSupportedApi(fakeThreadUtils);
    failingResponse =
        createHttpResponse(/* responseCode= */ NOT_FOUND, Response.getDefaultInstance());
    consumer =
        new RequiredConsumer<>(
            input -> {
              consumedResult = input;
            });
    ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", VERSION_CODES.KITKAT);
    ReflectionHelpers.setStaticField(Build.VERSION.class, "RELEASE", "4.4.3");
    ReflectionHelpers.setStaticField(Build.class, "CPU_ABI", "armeabi");
    ReflectionHelpers.setStaticField(Build.class, "TAGS", "dev-keys");
    when(applicationInfo.getAppType()).thenReturn(ApplicationInfo.AppType.CHROME);
    when(applicationInfo.getArchitecture()).thenReturn(ApplicationInfo.Architecture.ARM);
    when(applicationInfo.getBuildType()).thenReturn(ApplicationInfo.BuildType.DEV);
    when(applicationInfo.getVersionString()).thenReturn(APP_VERSION_STRING);
    requestManager =
        new FeedRequestManagerImpl(
            configuration,
            fakeNetworkClient,
            fakeProtocolAdapter,
            feedExtensionRegistry,
            scheduler,
            fakeTaskQueue,
            timingUtils,
            fakeThreadUtils,
            fakeActionReader,
            context,
            applicationInfo,
            fakeMainThreadRunner,
            fakeBasicLoggingApi,
            fakeTooltipSupportedApi);
  }

  @Test
  public void testTriggerRefresh() throws Exception {
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    assertThat(fakeTooltipSupportedApi.getLatestFeatureName()).isNull();

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);
    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testTriggerRefresh_FeedUiCapabilityAddedWhenFlagIsOn() throws Exception {
    testCapabilityAdded(ConfigKey.FEED_UI_ENABLED, Capability.FEED_UI);
  }

  @Test
  public void testTriggerRefresh_undoableActionCapabilityAddedWhenFlagIsOn() throws Exception {
    testCapabilityAdded(ConfigKey.UNDOABLE_ACTIONS_ENABLED, Capability.UNDOABLE_ACTIONS);
  }

  @Test
  public void testTriggerRefresh_manageInterestsCapabilityAddedWhenFlagIsOn() throws Exception {
    testCapabilityAdded(ConfigKey.MANAGE_INTERESTS_ENABLED, Capability.MANAGE_INTERESTS);
  }

  @Test
  public void testTriggerRefresh_tooltipCapabilityAddedWhenFlagIsOn() throws Exception {
    testCapabilityAdded(ConfigKey.CARD_MENU_TOOLTIP_ELIGIBLE, Capability.CARD_MENU_TOOLTIP);
  }

  @Test
  public void testTriggerRefresh_tooltipCapabilityNotAdded() throws Exception {
    // If the config key for card menu tool tip is set but the
    // TooltipSupportedApi.wouldTriggerHelpUi() returns false, then the capability should not be
    // added and only the BASE_UI should be present.
    fakeTooltipSupportedApi.addUnsupportedFeature(FeatureName.CARD_MENU_TOOLTIP);
    testCapabilityAdded(ConfigKey.CARD_MENU_TOOLTIP_ELIGIBLE, /* capability= */ null);
  }

  @Test
  public void testTriggerRefresh_useSecondaryPageRequestAdded() throws Exception {
    testCapabilityAdded(
        ConfigKey.USE_SECONDARY_PAGE_REQUEST, Capability.USE_SECONDARY_PAGE_REQUEST);
  }

  @Test
  public void testTriggerRefresh_articleSnippetsAdded() throws Exception {
    testCapabilityAdded(ConfigKey.SNIPPETS_ENABLED, Capability.ARTICLE_SNIPPETS);
  }

  @Test
  public void testTriggerRefresh_enableCarouselsAdded() throws Exception {
    testCapabilityAdded(ConfigKey.ENABLE_CAROUSELS, Capability.CAROUSELS);
  }

  @Test
  public void testActionData_simpleDismiss() throws Exception {
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, null));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Collections.singletonList(ID);
    List<String> expectedContentDomains = Collections.singletonList(CONTENT_DOMAIN);
    List<String> expectedTables = Collections.singletonList(TABLE);
    List<SemanticProperties> expectedSemanticProperties = Collections.emptyList();
    List<FeedActionQueryDataItem> expectedDataItems =
        Collections.singletonList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_uniqueDismisses() throws Exception {
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, null),
        buildDismissAction(ID_2, CONTENT_DOMAIN_2, TABLE_2, null));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Arrays.asList(ID, ID_2);
    List<String> expectedContentDomains = Arrays.asList(CONTENT_DOMAIN, CONTENT_DOMAIN_2);
    List<String> expectedTables = Arrays.asList(TABLE, TABLE_2);
    List<SemanticProperties> expectedSemanticProperties = Collections.emptyList();
    List<FeedActionQueryDataItem> expectedDataItems =
        Arrays.asList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .build(),
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(1)
                .setContentDomainIndex(1)
                .setTableIndex(1)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_overlappingDismisses() throws Exception {
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, null),
        buildDismissAction(ID_2, CONTENT_DOMAIN, TABLE, null));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Arrays.asList(ID, ID_2);
    List<String> expectedContentDomains = Collections.singletonList(CONTENT_DOMAIN);
    List<String> expectedTables = Collections.singletonList(TABLE);
    List<SemanticProperties> expectedSemanticProperties = Collections.emptyList();
    List<FeedActionQueryDataItem> expectedDataItems =
        Arrays.asList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .build(),
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(1)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_simpleDismissWithSemanticProperties() throws Exception {
    byte[] semanticPropertiesBytes = {42, 17, 88};
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, semanticPropertiesBytes));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Collections.singletonList(ID);
    List<String> expectedContentDomains = Collections.singletonList(CONTENT_DOMAIN);
    List<String> expectedTables = Collections.singletonList(TABLE);
    List<SemanticProperties> expectedSemanticProperties =
        Collections.singletonList(
            SemanticProperties.newBuilder()
                .setSemanticPropertiesData(ByteString.copyFrom(semanticPropertiesBytes))
                .build());
    List<FeedActionQueryDataItem> expectedDataItems =
        Collections.singletonList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .setSemanticPropertiesIndex(0)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_uniqueDismissesWithSemanticProperties() throws Exception {
    byte[] semanticPropertiesBytes = {42, 17, 88};
    byte[] semanticPropertiesBytes2 = {7, 43, 91};
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, semanticPropertiesBytes),
        buildDismissAction(ID_2, CONTENT_DOMAIN_2, TABLE_2, semanticPropertiesBytes2));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Arrays.asList(ID, ID_2);
    List<String> expectedContentDomains = Arrays.asList(CONTENT_DOMAIN, CONTENT_DOMAIN_2);
    List<String> expectedTables = Arrays.asList(TABLE, TABLE_2);
    List<SemanticProperties> expectedSemanticProperties =
        Arrays.asList(
            SemanticProperties.newBuilder()
                .setSemanticPropertiesData(ByteString.copyFrom(semanticPropertiesBytes))
                .build(),
            SemanticProperties.newBuilder()
                .setSemanticPropertiesData(ByteString.copyFrom(semanticPropertiesBytes2))
                .build());
    List<FeedActionQueryDataItem> expectedDataItems =
        Arrays.asList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .setSemanticPropertiesIndex(0)
                .build(),
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(1)
                .setContentDomainIndex(1)
                .setTableIndex(1)
                .setSemanticPropertiesIndex(1)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_overlappingDismissesWithSemanticProperties() throws Exception {
    byte[] semanticPropertiesBytes = {42, 17, 88};
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, semanticPropertiesBytes),
        buildDismissAction(ID_2, CONTENT_DOMAIN, TABLE_2, semanticPropertiesBytes));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Arrays.asList(ID, ID_2);
    List<String> expectedContentDomains = Collections.singletonList(CONTENT_DOMAIN);
    List<String> expectedTables = Arrays.asList(TABLE, TABLE_2);
    List<SemanticProperties> expectedSemanticProperties =
        Collections.singletonList(
            SemanticProperties.newBuilder()
                .setSemanticPropertiesData(ByteString.copyFrom(semanticPropertiesBytes))
                .build());
    List<FeedActionQueryDataItem> expectedDataItems =
        Arrays.asList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .setSemanticPropertiesIndex(0)
                .build(),
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(1)
                .setContentDomainIndex(0)
                .setTableIndex(1)
                .setSemanticPropertiesIndex(0)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testActionData_someDismissesWithSemanticProperties() throws Exception {
    byte[] semanticPropertiesBytes = {42, 17, 88};
    fakeActionReader.addDismissActionsWithSemanticProperties(
        buildDismissAction(ID, CONTENT_DOMAIN, TABLE, null),
        buildDismissAction(ID_2, CONTENT_DOMAIN_2, TABLE_2, semanticPropertiesBytes));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Request request = getRequestFromHttpRequest(httpRequest);

    List<Long> expectedIds = Arrays.asList(ID, ID_2);
    List<String> expectedContentDomains = Arrays.asList(CONTENT_DOMAIN, CONTENT_DOMAIN_2);
    List<String> expectedTables = Arrays.asList(TABLE, TABLE_2);
    List<SemanticProperties> expectedSemanticProperties =
        Collections.singletonList(
            SemanticProperties.newBuilder()
                .setSemanticPropertiesData(ByteString.copyFrom(semanticPropertiesBytes))
                .build());
    List<FeedActionQueryDataItem> expectedDataItems =
        Arrays.asList(
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(0)
                .setContentDomainIndex(0)
                .setTableIndex(0)
                .build(),
            FeedActionQueryDataItem.newBuilder()
                .setIdIndex(1)
                .setContentDomainIndex(1)
                .setTableIndex(1)
                .setSemanticPropertiesIndex(0)
                .build());

    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .addFeedActionQueryData(
                        FeedActionQueryData.newBuilder()
                            .setAction(Action.newBuilder().setActionType(ActionType.DISMISS))
                            .addAllUniqueId(expectedIds)
                            .addAllUniqueContentDomain(expectedContentDomains)
                            .addAllUniqueTable(expectedTables)
                            .addAllUniqueSemanticProperties(expectedSemanticProperties)
                            .addAllFeedActionQueryDataItem(expectedDataItems))
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  @Test
  public void testHandleResponse() throws Exception {
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, consumer);

    assertThat(fakeProtocolAdapter.getLastResponse()).isEqualToDefaultInstance();
    assertThat(consumer.isCalled()).isTrue();
    assertThat(consumedResult.isSuccessful()).isTrue();
  }

  @Test
  public void testHandleResponse_notFound() throws Exception {
    fakeNetworkClient.addResponse(failingResponse);
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, consumer);

    verify(scheduler).onRequestError(NOT_FOUND);
    assertThat(consumer.isCalled()).isTrue();
    assertThat(consumedResult.isSuccessful()).isFalse();
  }

  @Test
  public void testHandleResponse_pageNotFound() throws Exception {
    fakeNetworkClient.addResponse(failingResponse);
    StreamToken token =
        StreamToken.newBuilder()
            .setNextPageToken(ByteString.copyFrom("abc", Charset.defaultCharset()))
            .build();
    fakeThreadUtils.enforceMainThread(false);
    requestManager.loadMore(token, ConsistencyToken.getDefaultInstance(), consumer);

    verify(scheduler, never()).onRequestError(NOT_FOUND);
    assertThat(consumer.isCalled()).isTrue();
    assertThat(consumedResult.isSuccessful()).isFalse();
  }

  @Test
  public void testHandleResponse_missingLengthPrefixNotSupported() {
    fakeNetworkClient.addResponse(
        new HttpResponse(/* responseCode= */ 200, Response.getDefaultInstance().toByteArray()));
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, consumer);
    assertThat(consumer.isCalled()).isTrue();
    assertThat(consumedResult.isSuccessful()).isFalse();
    assertThat(fakeProtocolAdapter.getLastResponse()).isNull();
  }

  @Test
  public void testGetWireRequestResponse_unknown() throws Exception {
    testReason(RequestReason.UNKNOWN, FeedQuery.RequestReason.UNKNOWN_REQUEST_REASON);
  }

  @Test
  public void testGetWireRequestResponse_zeroState() throws Exception {
    testReason(RequestReason.ZERO_STATE, FeedQuery.RequestReason.ZERO_STATE_REFRESH);
  }

  @Test
  public void testGetWireRequestResponse_hostRequested() throws Exception {
    testReason(RequestReason.HOST_REQUESTED, FeedQuery.RequestReason.SCHEDULED_REFRESH);
  }

  @Test
  public void testGetWireRequestResponse_openWithContent() throws Exception {
    testReason(RequestReason.OPEN_WITH_CONTENT, FeedQuery.RequestReason.WITH_CONTENT);
  }

  @Test
  public void testGetWireRequestResponse_manualContinuation() throws Exception {
    testReason(RequestReason.MANUAL_CONTINUATION, FeedQuery.RequestReason.NEXT_PAGE_SCROLL);
  }

  @Test
  public void testGetWireRequestResponse_automaticContinuation() throws Exception {
    testReason(RequestReason.AUTOMATIC_CONTINUATION, FeedQuery.RequestReason.NEXT_PAGE_SCROLL);
  }

  @Test
  public void testGetWireRequestResponse_openWithoutContent() throws Exception {
    testReason(RequestReason.OPEN_WITHOUT_CONTENT, FeedQuery.RequestReason.INITIAL_LOAD);
  }

  @Test
  public void testGetWireRequestResponse_clearAll() throws Exception {
    testReason(RequestReason.CLEAR_ALL, FeedQuery.RequestReason.CLEAR_ALL);
  }

  @Test
  @Config(qualifiers = "en-rGB", sdk = VERSION_CODES.LOLLIPOP)
  public void testClientInfo_postLollipop() throws Exception {
    ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", VERSION_CODES.LOLLIPOP);
    ReflectionHelpers.setStaticField(Build.VERSION.class, "RELEASE", "7.1.2b4.1");
    ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", new String[] {"arm64-v8a"});
    ReflectionHelpers.setStaticField(Build.class, "CPU_ABI", "armeabi");
    ReflectionHelpers.setStaticField(Build.class, "TAGS", "release-keys");
    when(applicationInfo.getAppType()).thenReturn(ApplicationInfo.AppType.SEARCH_APP);
    when(applicationInfo.getArchitecture()).thenReturn(ApplicationInfo.Architecture.ARM64);
    when(applicationInfo.getBuildType()).thenReturn(ApplicationInfo.BuildType.RELEASE);
    when(applicationInfo.getVersionString()).thenReturn("1.2.3.4");

    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();

    Request request = getRequestFromHttpRequest(httpRequest);
    Request expectedRequest =
        Request.newBuilder()
            .setRequestVersion(RequestVersion.FEED_QUERY)
            .setExtension(
                FeedRequest.feedRequest,
                getTestFeedRequestBuilder()
                    .setFeedQuery(
                        FeedQuery.newBuilder().setReason(FeedQuery.RequestReason.SCHEDULED_REFRESH))
                    .setClientInfo(
                        ClientInfo.newBuilder()
                            .setPlatformType(PlatformType.ANDROID)
                            .setPlatformVersion(
                                Version.newBuilder()
                                    .setMajor(7)
                                    .setMinor(1)
                                    .setBuild(2)
                                    .setRevision(1)
                                    .setArchitecture(Architecture.ARM64)
                                    .setBuildType(BuildType.RELEASE)
                                    .setApiVersion(VERSION_CODES.LOLLIPOP)
                                    .build())
                            .setLocale(LocaleUtils.getLanguageTag(context))
                            .setAppType(AppType.GSA)
                            .setAppVersion(
                                Version.newBuilder()
                                    .setMajor(1)
                                    .setMinor(2)
                                    .setBuild(3)
                                    .setRevision(4)
                                    .setArchitecture(Architecture.ARM64)
                                    .setBuildType(BuildType.RELEASE)
                                    .build())
                            .addDisplayInfo(
                                DisplayInfo.newBuilder()
                                    .setScreenDensity(1.0f)
                                    .setScreenWidthInPixels(320)
                                    .setScreenHeightInPixels(470))
                            .build())
                    .addClientCapability(Capability.BASE_UI)
                    .build())
            .build();
    assertThat(request).isEqualTo(expectedRequest);
  }

  private void testReason(@RequestReason int reason, FeedQuery.RequestReason expectedReason)
      throws Exception {
    fakeNetworkClient.addResponse(failingResponse);
    requestManager.triggerRefresh(reason, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    Request request = getRequestFromHttpRequest(httpRequest);
    assertThat(request.getExtension(FeedRequest.feedRequest).getFeedQuery().getReason())
        .isEqualTo(expectedReason);
    assertThat(fakeBasicLoggingApi.serverRequestReason).isEqualTo(reason);
  }

  private static void assertHttpRequestFormattedCorrectly(
      HttpRequest httpRequest, Context context) {
    assertThat(httpRequest.getBody()).hasLength(0);
    assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.GET);
    assertThat(httpRequest.getUri().getQueryParameter("fmt")).isEqualTo("bin");
    assertThat(httpRequest.getUri().getQueryParameter(RequestHelper.MOTHERSHIP_PARAM_PAYLOAD))
        .isNotNull();
    assertThat(httpRequest.getUri().getQueryParameter(RequestHelper.LOCALE_PARAM))
        .isEqualTo(LocaleUtils.getLanguageTag(context));
  }

  private static HttpResponse createHttpResponse(int responseCode, Response response)
      throws IOException {
    byte[] rawResponse = response.toByteArray();
    ByteBuffer buffer = ByteBuffer.allocate(rawResponse.length + (Integer.SIZE / 8));
    CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(buffer);
    codedOutputStream.writeUInt32NoTag(rawResponse.length);
    codedOutputStream.writeRawBytes(rawResponse);
    codedOutputStream.flush();
    return new HttpResponse(responseCode, buffer.array());
  }

  private static DismissActionWithSemanticProperties buildDismissAction(
      long id, String contentDomain, String table, byte /*@Nullable*/ [] semanticProperties) {
    ContentId contentId =
        ContentId.newBuilder().setTable(table).setContentDomain(contentDomain).setId(id).build();
    return new DismissActionWithSemanticProperties(contentId, semanticProperties);
  }

  private Request getRequestFromHttpRequest(HttpRequest httpRequest) throws Exception {
    return Request.parseFrom(
        Base64.decode(
            httpRequest.getUri().getQueryParameter(RequestHelper.MOTHERSHIP_PARAM_PAYLOAD),
            Base64.URL_SAFE),
        registry);
  }

  private static FeedRequest.Builder getTestFeedRequestBuilder() {
    return FeedRequest.newBuilder()
        .setConsistencyToken(ConsistencyToken.getDefaultInstance())
        .setClientInfo(
            ClientInfo.newBuilder()
                .setPlatformType(PlatformType.ANDROID)
                .setPlatformVersion(
                    Version.newBuilder()
                        .setMajor(4)
                        .setMinor(4)
                        .setBuild(3)
                        .setArchitecture(Architecture.ARM)
                        .setBuildType(BuildType.DEV)
                        .setApiVersion(VERSION_CODES.KITKAT)
                        .build())
                .setLocale(Locale.US.toLanguageTag())
                .setAppType(AppType.CHROME)
                .setAppVersion(
                    Version.newBuilder()
                        .setMajor(5)
                        .setMinor(7)
                        .setArchitecture(Architecture.ARM)
                        .setBuildType(BuildType.DEV)
                        .build())
                .addDisplayInfo(
                    DisplayInfo.newBuilder()
                        .setScreenDensity(1.0f)
                        .setScreenWidthInPixels(320)
                        .setScreenHeightInPixels(470))
                .build());
  }

  private void testCapabilityAdded(String configKey, Capability capability) throws Exception {
    Configuration configuration = new Configuration.Builder().put(configKey, true).build();
    requestManager =
        new FeedRequestManagerImpl(
            configuration,
            fakeNetworkClient,
            fakeProtocolAdapter,
            new FeedExtensionRegistry(ArrayList::new),
            scheduler,
            fakeTaskQueue,
            timingUtils,
            fakeThreadUtils,
            fakeActionReader,
            context,
            applicationInfo,
            fakeMainThreadRunner,
            fakeBasicLoggingApi,
            fakeTooltipSupportedApi);
    requestManager.triggerRefresh(RequestReason.HOST_REQUESTED, input -> {});

    HttpRequest httpRequest = fakeNetworkClient.getLatestRequest();
    assertHttpRequestFormattedCorrectly(httpRequest, context);

    Set<Capability> expectedCap = EnumSet.of(Capability.BASE_UI);
    if (capability != null) {
      expectedCap.add(capability);
    }

    Request request = getRequestFromHttpRequest(httpRequest);
    assertThat(request.getExtension(FeedRequest.feedRequest).getClientCapabilityList())
        .containsExactlyElementsIn(expectedCap);
  }
}
