chromium/chromecast/base/java/test/org/chromium/chromecast/base/ObservableAlarmTest.java

// Copyright 2022 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.chromecast.base;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.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 org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.mockito.ArgumentCaptor;

import org.chromium.chromecast.base.Observable.Scheduler;

/**
 * Tests for Observable#alarm().
 */
@RunWith(BlockJUnit4ClassRunner.class)
public class ObservableAlarmTest {
    @Test
    public void testAlarmDoesNotStartWithoutBeingSubscribedTo() {
        Scheduler scheduler = mock(Scheduler.class);
        Observable<?> a = Observable.alarm(scheduler, 100L);
        verify(scheduler, never()).postDelayed(any(), anyLong());
    }

    @Test
    public void testAlarmStartsForEachObserver() {
        Scheduler scheduler = mock(Scheduler.class);
        Observable<?> a = Observable.alarm(scheduler, 100L);
        ReactiveRecorder recorder1 = ReactiveRecorder.record(a);
        ReactiveRecorder recorder2 = ReactiveRecorder.record(a);
        recorder1.verify().end();
        recorder2.verify().end();
        verify(scheduler, times(2)).postDelayed(any(), eq(100L));
    }

    @Test
    public void testPostedRunnableResolvesCallback() {
        Scheduler scheduler = mock(Scheduler.class);
        ArgumentCaptor<Runnable> taskCaptor = ArgumentCaptor.forClass(Runnable.class);
        Observable<?> a = Observable.alarm(scheduler, 100L);
        ReactiveRecorder recorder = ReactiveRecorder.record(a);
        verify(scheduler).postDelayed(taskCaptor.capture(), eq(100L));
        Runnable delayedTask = taskCaptor.getValue();
        delayedTask.run();
        recorder.verify().opened(Unit.unit()).end();
    }

    @Test
    public void testDoesNotNotifyObserverAfterUnsubscribe() {
        Scheduler scheduler = mock(Scheduler.class);
        ArgumentCaptor<Runnable> taskCaptor = ArgumentCaptor.forClass(Runnable.class);
        Observable<?> a = Observable.alarm(scheduler, 100L);
        ReactiveRecorder recorder = ReactiveRecorder.record(a);
        verify(scheduler).postDelayed(taskCaptor.capture(), eq(100L));
        Runnable delayedTask = taskCaptor.getValue();
        recorder.unsubscribe();
        delayedTask.run();
        recorder.verify().end();
    }

    @Test
    public void testNotifiesObserverAsynchronouslyWhenDelayIsZero() {
        Scheduler scheduler = mock(Scheduler.class);
        ArgumentCaptor<Runnable> taskCaptor = ArgumentCaptor.forClass(Runnable.class);
        Observable<?> a = Observable.alarm(scheduler, 0L);
        ReactiveRecorder recorder = ReactiveRecorder.record(a);
        verify(scheduler).postDelayed(taskCaptor.capture(), eq(0L));
        recorder.verify().end();
        Runnable delayedTask = taskCaptor.getValue();
        delayedTask.run();
        recorder.verify().opened(Unit.unit()).end();
    }
}