blob: 6f18315cd1b115b59971a5781098a12ad00d43b0 [file] [log] [blame]
// Copyright 2019 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.feedsessionmanager.internal;
import static com.google.android.libraries.feed.api.internal.common.testing.ContentIdGenerators.ROOT_PREFIX;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.MockitoAnnotations.initMocks;
import com.google.android.libraries.feed.api.host.config.Configuration;
import com.google.android.libraries.feed.api.internal.common.testing.ContentIdGenerators;
import com.google.android.libraries.feed.api.internal.common.testing.InternalProtocolBuilder;
import com.google.android.libraries.feed.api.internal.store.Store;
import com.google.android.libraries.feed.common.Result;
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.time.TimingUtils;
import com.google.android.libraries.feed.common.time.testing.FakeClock;
import com.google.android.libraries.feed.feedsessionmanager.internal.HeadAsStructure.TreeNode;
import com.google.android.libraries.feed.testing.store.FakeStore;
import com.google.search.now.feed.client.StreamDataProto.StreamFeature;
import com.google.search.now.feed.client.StreamDataProto.StreamPayload;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests of the {@link HeadAsStructure}. */
@RunWith(RobolectricTestRunner.class)
public class HeadAsStructureTest {
private final ContentIdGenerators idGenerators = new ContentIdGenerators();
private final FakeThreadUtils fakeThreadUtils = FakeThreadUtils.withThreadChecks();
private final String rootContentId = idGenerators.createRootContentId(0);
private final TimingUtils timingUtils = new TimingUtils();
private final FakeClock fakeClock = new FakeClock();
private FakeStore fakeStore;
@Before
public void setUp() {
initMocks(this);
fakeStore =
new FakeStore(
Configuration.getDefaultInstance(),
fakeThreadUtils,
new FakeTaskQueue(fakeClock, fakeThreadUtils),
fakeClock);
fakeThreadUtils.enforceMainThread(false);
}
@Test
public void testUninitialized() {
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
Result<List<Void>> result = headAsStructure.filter(payload -> null);
assertThat(result.isSuccessful()).isFalse();
}
@Test
public void testInitialization() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
assertThat(headAsStructure.root).isNotNull();
assertThat(headAsStructure.content).hasSize(4);
assertThat(headAsStructure.tree).hasSize(4);
TreeNode root = headAsStructure.content.get(rootContentId);
assertThat(root).isNotNull();
assertThat(headAsStructure.root).isEqualTo(root);
List<TreeNode> rootChildren = headAsStructure.tree.get(rootContentId);
assertThat(rootChildren).isNotNull();
assertThat(rootChildren).hasSize(3);
}
@Test
public void testInitialization_withRemove() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
String contentId = idGenerators.createFeatureContentId(2);
protocolBuilder.removeFeature(contentId, rootContentId);
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
assertThat(headAsStructure.root).isNotNull();
assertThat(headAsStructure.content).hasSize(3);
assertThat(headAsStructure.tree).hasSize(3);
List<TreeNode> rootChildren = headAsStructure.tree.get(rootContentId);
assertThat(rootChildren).isNotNull();
assertThat(rootChildren).hasSize(2);
}
@Test
public void testInitialization_doubleInitialization() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isFalse());
}
@Test
public void testInitialization_buildTreeFailure() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore.setAllowGetStreamStructures(false).setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isFalse());
}
@Test
public void testInitialization_bindTreeFailure() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setAllowGetPayloads(false);
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isFalse());
}
@Test
public void testFiltering_payload() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
Result<List<StreamFeature>> results =
headAsStructure.filter(
node -> {
StreamPayload payload = node.getStreamPayload();
assertThat(payload).isNotNull();
if (payload.hasStreamFeature()) {
return payload.getStreamFeature();
} else {
return null;
}
});
assertThat(results.isSuccessful()).isTrue();
assertThat(results.getValue()).hasSize(4);
}
@Test
public void testFiltering_childrenOfRoot() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
Result<List<String>> results =
headAsStructure.filter(
node ->
!node.getStreamStructure().getContentId().startsWith(ROOT_PREFIX)
? node.getStreamStructure().getContentId()
: null);
assertThat(results.isSuccessful()).isTrue();
assertThat(results.getValue()).hasSize(3);
}
@Test
public void testFiltering_withRemove() {
InternalProtocolBuilder protocolBuilder = new InternalProtocolBuilder();
protocolBuilder.addClearOperation().addRootFeature();
for (int i = 0; i < 3; i++) {
String contentId = idGenerators.createFeatureContentId(i);
protocolBuilder.addFeature(contentId, rootContentId);
}
String contentId = idGenerators.createFeatureContentId(2);
protocolBuilder.removeFeature(contentId, rootContentId);
fakeStore
.setStreamStructures(Store.HEAD_SESSION_ID, protocolBuilder.buildAsStreamStructure())
.setContent(protocolBuilder.buildAsPayloadWithId());
HeadAsStructure headAsStructure = new HeadAsStructure(fakeStore, timingUtils, fakeThreadUtils);
headAsStructure.initialize(result -> assertThat(result.isSuccessful()).isTrue());
Result<List<StreamFeature>> results =
headAsStructure.filter(
node -> {
StreamPayload payload = node.getStreamPayload();
assertThat(payload).isNotNull();
if (payload.hasStreamFeature()) {
return payload.getStreamFeature();
} else {
return null;
}
});
assertThat(results.isSuccessful()).isTrue();
assertThat(results.getValue()).hasSize(3);
}
}