mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Partial migration of data package to Kotlin
This commit is contained in:
		@@ -0,0 +1,140 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.library;
 | 
			
		||||
 | 
			
		||||
import android.app.AlarmManager;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.SystemClock;
 | 
			
		||||
 | 
			
		||||
import org.assertj.core.data.Offset;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.robolectric.RobolectricGradleTestRunner;
 | 
			
		||||
import org.robolectric.annotation.Config;
 | 
			
		||||
import org.robolectric.shadows.ShadowAlarmManager;
 | 
			
		||||
import org.robolectric.shadows.ShadowApplication;
 | 
			
		||||
import org.robolectric.shadows.ShadowPendingIntent;
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.CustomBuildConfig;
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.Mockito.spy;
 | 
			
		||||
import static org.robolectric.Shadows.shadowOf;
 | 
			
		||||
 | 
			
		||||
@Config(constants = CustomBuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
 | 
			
		||||
@RunWith(RobolectricGradleTestRunner.class)
 | 
			
		||||
public class LibraryUpdateAlarmTest {
 | 
			
		||||
 | 
			
		||||
    ShadowApplication app;
 | 
			
		||||
    Context context;
 | 
			
		||||
    ShadowAlarmManager alarmManager;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setup() {
 | 
			
		||||
        app = ShadowApplication.getInstance();
 | 
			
		||||
        context = spy(app.getApplicationContext());
 | 
			
		||||
 | 
			
		||||
        alarmManager = shadowOf((AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLibraryIntentHandling() {
 | 
			
		||||
        Intent intent = new Intent(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION);
 | 
			
		||||
        assertThat(app.hasReceiverForIntent(intent)).isTrue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAlarmIsNotStarted() {
 | 
			
		||||
        assertThat(alarmManager.getNextScheduledAlarm()).isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAlarmIsNotStartedWhenBootReceivedAndSettingZero() {
 | 
			
		||||
        LibraryUpdateAlarm alarm = new LibraryUpdateAlarm();
 | 
			
		||||
        alarm.onReceive(context, new Intent(Intent.ACTION_BOOT_COMPLETED));
 | 
			
		||||
 | 
			
		||||
        assertThat(alarmManager.getNextScheduledAlarm()).isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAlarmIsStartedWhenBootReceivedAndSettingNotZero() {
 | 
			
		||||
        PreferencesHelper prefs = new PreferencesHelper(context);
 | 
			
		||||
        prefs.libraryUpdateInterval().set(1);
 | 
			
		||||
 | 
			
		||||
        LibraryUpdateAlarm alarm = new LibraryUpdateAlarm();
 | 
			
		||||
        alarm.onReceive(context, new Intent(Intent.ACTION_BOOT_COMPLETED));
 | 
			
		||||
 | 
			
		||||
        assertThat(alarmManager.getNextScheduledAlarm()).isNotNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testOnlyOneAlarmExists() {
 | 
			
		||||
        PreferencesHelper prefs = new PreferencesHelper(context);
 | 
			
		||||
        prefs.libraryUpdateInterval().set(1);
 | 
			
		||||
 | 
			
		||||
        LibraryUpdateAlarm.startAlarm(context);
 | 
			
		||||
        LibraryUpdateAlarm.startAlarm(context);
 | 
			
		||||
        LibraryUpdateAlarm.startAlarm(context);
 | 
			
		||||
 | 
			
		||||
        assertThat(alarmManager.getScheduledAlarms()).hasSize(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLibraryWillBeUpdatedWhenAlarmFired() {
 | 
			
		||||
        PreferencesHelper prefs = new PreferencesHelper(context);
 | 
			
		||||
        prefs.libraryUpdateInterval().set(1);
 | 
			
		||||
 | 
			
		||||
        Intent expectedIntent = new Intent(context, LibraryUpdateAlarm.class);
 | 
			
		||||
        expectedIntent.setAction(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION);
 | 
			
		||||
 | 
			
		||||
        LibraryUpdateAlarm.startAlarm(context);
 | 
			
		||||
 | 
			
		||||
        ShadowAlarmManager.ScheduledAlarm scheduledAlarm = alarmManager.getNextScheduledAlarm();
 | 
			
		||||
        ShadowPendingIntent pendingIntent = shadowOf(scheduledAlarm.operation);
 | 
			
		||||
        assertThat(pendingIntent.isBroadcastIntent()).isTrue();
 | 
			
		||||
        assertThat(pendingIntent.getSavedIntents()).hasSize(1);
 | 
			
		||||
        assertThat(expectedIntent.getComponent()).isEqualTo(pendingIntent.getSavedIntents()[0].getComponent());
 | 
			
		||||
        assertThat(expectedIntent.getAction()).isEqualTo(pendingIntent.getSavedIntents()[0].getAction());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLibraryUpdateServiceIsStartedWhenUpdateIntentIsReceived() {
 | 
			
		||||
        Intent intent = new Intent(context, LibraryUpdateService.class);
 | 
			
		||||
        assertThat(app.getNextStartedService()).isNotEqualTo(intent);
 | 
			
		||||
 | 
			
		||||
        LibraryUpdateAlarm alarm = new LibraryUpdateAlarm();
 | 
			
		||||
        alarm.onReceive(context, new Intent(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION));
 | 
			
		||||
 | 
			
		||||
        assertThat(app.getNextStartedService()).isEqualTo(intent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testReceiverDoesntReactToNullActions() {
 | 
			
		||||
        PreferencesHelper prefs = new PreferencesHelper(context);
 | 
			
		||||
        prefs.libraryUpdateInterval().set(1);
 | 
			
		||||
 | 
			
		||||
        Intent intent = new Intent(context, LibraryUpdateService.class);
 | 
			
		||||
 | 
			
		||||
        LibraryUpdateAlarm alarm = new LibraryUpdateAlarm();
 | 
			
		||||
        alarm.onReceive(context, new Intent());
 | 
			
		||||
 | 
			
		||||
        assertThat(app.getNextStartedService()).isNotEqualTo(intent);
 | 
			
		||||
        assertThat(alarmManager.getScheduledAlarms()).hasSize(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAlarmFiresCloseToDesiredTime() {
 | 
			
		||||
        int hours = 2;
 | 
			
		||||
        LibraryUpdateAlarm.startAlarm(context, hours);
 | 
			
		||||
 | 
			
		||||
        long shouldRunAt = SystemClock.elapsedRealtime() + (hours * 60 * 60 * 1000);
 | 
			
		||||
 | 
			
		||||
        // Margin error of 3 seconds
 | 
			
		||||
        Offset<Long> offset = Offset.offset(3 * 1000L);
 | 
			
		||||
 | 
			
		||||
        assertThat(alarmManager.getNextScheduledAlarm().triggerAtTime).isCloseTo(shouldRunAt, offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,130 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.library;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.util.Pair;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.robolectric.Robolectric;
 | 
			
		||||
import org.robolectric.RobolectricGradleTestRunner;
 | 
			
		||||
import org.robolectric.annotation.Config;
 | 
			
		||||
import org.robolectric.shadows.ShadowApplication;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.CustomBuildConfig;
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Chapter;
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga;
 | 
			
		||||
import eu.kanade.tachiyomi.data.source.base.Source;
 | 
			
		||||
import rx.Observable;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.Matchers.any;
 | 
			
		||||
import static org.mockito.Matchers.anyInt;
 | 
			
		||||
import static org.mockito.Matchers.eq;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
import static org.mockito.Mockito.never;
 | 
			
		||||
import static org.mockito.Mockito.times;
 | 
			
		||||
import static org.mockito.Mockito.verify;
 | 
			
		||||
import static org.mockito.Mockito.when;
 | 
			
		||||
 | 
			
		||||
@Config(constants = CustomBuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
 | 
			
		||||
@RunWith(RobolectricGradleTestRunner.class)
 | 
			
		||||
public class LibraryUpdateServiceTest {
 | 
			
		||||
 | 
			
		||||
    ShadowApplication app;
 | 
			
		||||
    Context context;
 | 
			
		||||
    LibraryUpdateService service;
 | 
			
		||||
    Source source;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setup() {
 | 
			
		||||
        app = ShadowApplication.getInstance();
 | 
			
		||||
        context = app.getApplicationContext();
 | 
			
		||||
        service = Robolectric.setupService(LibraryUpdateService.class);
 | 
			
		||||
        source = mock(Source.class);
 | 
			
		||||
        when(service.sourceManager.get(anyInt())).thenReturn(source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testStartCommand() {
 | 
			
		||||
        service.onStartCommand(new Intent(), 0, 0);
 | 
			
		||||
        verify(service.db).getFavoriteMangas();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLifecycle() {
 | 
			
		||||
        // Smoke test
 | 
			
		||||
        Robolectric.buildService(LibraryUpdateService.class)
 | 
			
		||||
                .attach()
 | 
			
		||||
                .create()
 | 
			
		||||
                .startCommand(0, 0)
 | 
			
		||||
                .destroy()
 | 
			
		||||
                .get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateManga() {
 | 
			
		||||
        Manga manga = Manga.create("manga1");
 | 
			
		||||
        List<Chapter> chapters = createChapters("/chapter1", "/chapter2");
 | 
			
		||||
 | 
			
		||||
        when(source.pullChaptersFromNetwork(manga.url)).thenReturn(Observable.just(chapters));
 | 
			
		||||
        when(service.db.insertOrRemoveChapters(manga, chapters))
 | 
			
		||||
                .thenReturn(Observable.just(Pair.create(2, 0)));
 | 
			
		||||
 | 
			
		||||
        service.updateManga(manga).subscribe();
 | 
			
		||||
 | 
			
		||||
        verify(service.db).insertOrRemoveChapters(manga, chapters);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testContinuesUpdatingWhenAMangaFails() {
 | 
			
		||||
        Manga manga1 = Manga.create("manga1");
 | 
			
		||||
        Manga manga2 = Manga.create("manga2");
 | 
			
		||||
        Manga manga3 = Manga.create("manga3");
 | 
			
		||||
 | 
			
		||||
        List<Manga> favManga = createManga("manga1", "manga2", "manga3");
 | 
			
		||||
 | 
			
		||||
        List<Chapter> chapters = createChapters("/chapter1", "/chapter2");
 | 
			
		||||
        List<Chapter> chapters3 = createChapters("/achapter1", "/achapter2");
 | 
			
		||||
 | 
			
		||||
        when(service.db.getFavoriteMangas().executeAsBlocking()).thenReturn(favManga);
 | 
			
		||||
 | 
			
		||||
        // One of the updates will fail
 | 
			
		||||
        when(source.pullChaptersFromNetwork("manga1")).thenReturn(Observable.just(chapters));
 | 
			
		||||
        when(source.pullChaptersFromNetwork("manga2")).thenReturn(Observable.error(new Exception()));
 | 
			
		||||
        when(source.pullChaptersFromNetwork("manga3")).thenReturn(Observable.just(chapters3));
 | 
			
		||||
 | 
			
		||||
        when(service.db.insertOrRemoveChapters(manga1, chapters)).thenReturn(Observable.just(Pair.create(2, 0)));
 | 
			
		||||
        when(service.db.insertOrRemoveChapters(manga3, chapters)).thenReturn(Observable.just(Pair.create(2, 0)));
 | 
			
		||||
 | 
			
		||||
        service.updateLibrary().subscribe();
 | 
			
		||||
 | 
			
		||||
        // There are 3 network attempts and 2 insertions (1 request failed)
 | 
			
		||||
        verify(source, times(3)).pullChaptersFromNetwork(any());
 | 
			
		||||
        verify(service.db, times(2)).insertOrRemoveChapters(any(), any());
 | 
			
		||||
        verify(service.db, never()).insertOrRemoveChapters(eq(manga2), any());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<Chapter> createChapters(String... urls) {
 | 
			
		||||
        List<Chapter> list = new ArrayList<>();
 | 
			
		||||
        for (String url : urls) {
 | 
			
		||||
            Chapter c = Chapter.create();
 | 
			
		||||
            c.url = url;
 | 
			
		||||
            list.add(c);
 | 
			
		||||
        }
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<Manga> createManga(String... urls) {
 | 
			
		||||
        List<Manga> list = new ArrayList<>();
 | 
			
		||||
        for (String url : urls) {
 | 
			
		||||
            Manga m = Manga.create(url);
 | 
			
		||||
            list.add(m);
 | 
			
		||||
        }
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user