/*
* Copyright 2015 Victor Albertos
*
* 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 io.rx_cache2.internal;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.observers.TestObserver;
import io.rx_cache2.ConfigProvider;
import io.rx_cache2.EvictProvider;
import io.rx_cache2.Reply;
import io.rx_cache2.Source;
import io.rx_cache2.internal.cache.EvictExpirableRecordsPersistence;
import io.rx_cache2.internal.cache.EvictExpiredRecordsPersistence;
import io.rx_cache2.internal.cache.EvictRecord;
import io.rx_cache2.internal.cache.GetDeepCopy;
import io.rx_cache2.internal.cache.HasRecordExpired;
import io.rx_cache2.internal.cache.RetrieveRecord;
import io.rx_cache2.internal.cache.SaveRecord;
import io.rx_cache2.internal.cache.TwoLayersCache;
import io.rx_cache2.internal.cache.memory.ReferenceMapMemory;
import io.rx_cache2.internal.common.BaseTest;
import io.rx_cache2.internal.migration.DoMigrations;
import org.junit.Test;
import static junit.framework.TestCase.assertNotNull;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
/**
* Created by victor on 28/12/15.
*/
public class ProcessorProvidersTest extends BaseTest {
private io.rx_cache2.internal.ProcessorProvidersBehaviour processorProvidersUT;
private TwoLayersCache twoLayersCacheMock;
private HasRecordExpired hasRecordExpired;
private EvictExpiredRecordsPersistence evictExpiredRecordsPersistence;
private GetDeepCopy getDeepCopy;
private DoMigrations doMigrations;
@Override public void setUp() {
super.setUp();
hasRecordExpired = new HasRecordExpired();
io.rx_cache2.internal.Memory memory = new ReferenceMapMemory();
EvictRecord evictRecord = new EvictRecord(memory,disk);
SaveRecord saveRecord = new SaveRecord(memory, disk, 100, new EvictExpirableRecordsPersistence(memory, disk, 100, null), null);
RetrieveRecord retrieveRecord = new RetrieveRecord(memory,disk, evictRecord, hasRecordExpired, null);
evictExpiredRecordsPersistence = new EvictExpiredRecordsPersistence(memory, disk, hasRecordExpired, null);
twoLayersCacheMock = new TwoLayersCache(evictRecord, retrieveRecord, saveRecord);
getDeepCopy = new GetDeepCopy(memory, disk, Jolyglot$.newInstance());
doMigrations = new DoMigrations(disk, null, null);
}
@Test public void When_First_Retrieve_Then_Source_Retrieved_Is_Cloud() {
TestObserver observerMock = getSubscriberCompleted(false, false, true, Loader.VALID, false);
Reply<Mock> reply = (Reply) observerMock.values().get(0);
assertThat(reply.getSource(), is(Source.CLOUD));
assertNotNull(reply.getData());
}
@Test public void When_Evict_Cache_Then_Source_Retrieved_Is_Cloud() {
TestObserver observerMock = getSubscriberCompleted(true, true, true, Loader.VALID, false);
Reply<Mock> reply = (Reply) observerMock.values().get(0);
assertThat(reply.getSource(), is(Source.CLOUD));
assertNotNull(reply.getData());
}
@Test public void When_No_Evict_Cache_Then_Source_Retrieved_Is_Not_Cloud() {
TestObserver observerMock = getSubscriberCompleted(true, false, true, Loader.VALID, false);
Reply<Mock> reply = (Reply) observerMock.values().get(0);
assertThat(reply.getSource(), is(not(Source.CLOUD)));
assertNotNull(reply.getData());
}
@Test public void When_No_Reply_Then_Get_Mock() {
TestObserver observerMock = getSubscriberCompleted(true, false, false, Loader.VALID, false);
Mock mock = (Mock) observerMock.values().get(0);
assertNotNull(mock);
}
@Test public void When_No_Loader_And_Not_Cache_Then_Get_Throw_Exception() {
TestObserver observerMock = getSubscriberCompleted(false, false, false, Loader.NULL, false);
assertThat(observerMock.errorCount(), is(1));
assertThat(observerMock.valueCount(), is(0));
}
@Test public void When_No_Loader_And_Cache_Expired_Then_Get_Throw_Exception() {
TestObserver observerMock = getSubscriberCompleted(true, true, false, Loader.NULL, false);
assertThat(observerMock.errorCount(), is(1));
assertThat(observerMock.valueCount(), is(0));
}
@Test public void When_No_Loader_And_Cache_Expired_But_Use_Expired_Data_If_Loader_Not_Available_Then_Get_Mock() {
processorProvidersUT = new io.rx_cache2.internal.ProcessorProvidersBehaviour(twoLayersCacheMock, false, evictExpiredRecordsPersistence,
getDeepCopy, doMigrations);
TestObserver observerMock =
getSubscriberCompleted(true, true, false, Loader.NULL, true);
assertThat(observerMock.errorCount(), is(0));
assertThat(observerMock.valueCount(), is(1));
}
@Test public void When_Loader_Throws_Exception_And_Cache_Expired_Then_Get_Throw_Exception() {
TestObserver observerMock = getSubscriberCompleted(true, true, false, Loader.EXCEPTION, false);
assertThat(observerMock.errorCount(), is(1));
assertThat(observerMock.valueCount(), is(0));
}
@Test public void When_Loader_Throws_Exception_And_Cache_Expired_But_Use_Expired_Data_If_Loader_Not_Available_Then_Get_Mock() {
processorProvidersUT = new io.rx_cache2.internal.ProcessorProvidersBehaviour(twoLayersCacheMock, false, evictExpiredRecordsPersistence,
getDeepCopy, doMigrations);
TestObserver observerMock = getSubscriberCompleted(true, true, false, Loader.EXCEPTION, true);
assertThat(observerMock.errorCount(), is(0));
assertThat(observerMock.valueCount(), is(1));
}
private TestObserver getSubscriberCompleted(boolean hasCache, final boolean evictCache,
boolean detailResponse, Loader loader, boolean useExpiredDataIfLoaderNotAvailable) {
Observable observable;
switch (loader) {
case VALID:
observable = Observable.just(new Mock("message"));
break;
case NULL:
observable = Observable.error(new RuntimeException("No data"));
break;
default:
observable = Observable.create(new ObservableOnSubscribe<Object>() {
@Override public void subscribe(ObservableEmitter<Object> e) throws Exception {
throw new RuntimeException("error");
}
});
break;
}
ConfigProvider configProvider = new ConfigProvider("mockKey",
null, null, detailResponse, true, false,
"", "", observable, new EvictProvider(evictCache));
if (hasCache) twoLayersCacheMock.save("mockKey", "", "", new Mock("message"), configProvider.getLifeTimeMillis(), configProvider.isExpirable(), configProvider.isEncrypted());
processorProvidersUT = new ProcessorProvidersBehaviour(twoLayersCacheMock, useExpiredDataIfLoaderNotAvailable, evictExpiredRecordsPersistence,
getDeepCopy, doMigrations);
TestObserver observerMock = processorProvidersUT.getData(configProvider).test();
observerMock.awaitTerminalEvent();
return observerMock;
}
enum Loader {
VALID, NULL, EXCEPTION
}
}