Newer
Older
vavr-effect / src / test / java / com / github / tonivade / vavr / effect / ScheduleTest.java
@Antonio Muñoz Antonio Muñoz on 9 May 2022 4 KB schedule test
/*
 * Copyright (c) 2022, Antonio Gabriel Muñoz Conejo <antoniogmc at gmail dot com>
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.vavr.effect;

import static com.github.tonivade.vavr.effect.Unit.unit;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.Duration;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import io.vavr.Tuple2;
import io.vavr.collection.List;
import io.vavr.collection.Seq;
import io.vavr.control.Either;

@ExtendWith(MockitoExtension.class)
class ScheduleTest {

  @Test
  void repeat(@Mock Consumer<String> console) {
    IO<Unit> print = IO.exec(() -> console.accept("hola"));
    Schedule<Unit, Unit> schedule = Schedule.<Unit>recurs(2).zipRight(Schedule.identity());
    
    IO<Unit> repeat = print.repeat(schedule);
    
    Unit result = repeat.unsafeRunSync();
    
    assertEquals(unit(), result);
    verify(console, times(3)).accept("hola");
  }

  @Test
  void repeatDelay(@Mock Consumer<String> console) {
    IO<Unit> print = IO.exec(() -> console.accept("hola"));
    Schedule<Unit, Unit> recurs = Schedule.<Unit>recurs(2).zipRight(Schedule.identity());
    Schedule<Unit, Integer> spaced = Schedule.spaced(Duration.ofMillis(500));
    Schedule<Unit, Unit> schedule = recurs.zipLeft(spaced);

    IO<Unit> repeat = print.repeat(schedule);
    IO<Tuple2<Duration, Unit>> timed = repeat.timed();
    
    Tuple2<Duration, Unit> result = timed.unsafeRunSync();
    
    assertTrue(result._1().toMillis() > 1000);
    verify(console, times(3)).accept("hola");
  }
  
  @Test
  void noRepeat(@Mock Consumer<String> console) {
    IO<Unit> print = IO.exec(() -> console.accept("hola"));
    IO<Unit> repeat = print.repeat(Schedule.never());
    
    Unit result = repeat.unsafeRunSync();
    
    assertEquals(unit(), result);
    verify(console).accept("hola");
  }

  @Test
  void retry(@Mock Supplier<String> console) {
    when(console.get())
      .thenThrow(RuntimeException.class)
      .thenReturn("hola");

    IO<String> read = IO.task(console::get);
    IO<String> retry = read.retry(Schedule.recurs(1));
    
    String provide = retry.unsafeRunSync();
    
    assertEquals("hola", provide);
    verify(console, times(2)).get();
  }

  @Test
  void retryDelay(@Mock Supplier<String> console) {
    when(console.get()).thenThrow(RuntimeException.class).thenReturn("hola");

    IO<String> read = IO.task(console::get);
    Schedule<Throwable, Integer> recurs = Schedule.recurs(2);
    Schedule<Throwable, Integer> spaced = Schedule.spaced(Duration.ofMillis(500));
    IO<Tuple2<Duration, String>> retry = read.retry(recurs.zip(spaced)).timed();
    
    Tuple2<Duration, String> result = retry.unsafeRunSync();
    
    assertTrue(result._1().toMillis() > 500);
    assertEquals("hola", result._2());
    verify(console, times(2)).get();
  }
  
  @Test
  void noRetry(@Mock Supplier<String> console) {
    when(console.get()).thenThrow(UnsupportedOperationException.class).thenReturn("hola");
    
    IO<String> read = IO.task(console::get);
    IO<String> retry = read.retry(Schedule.never());
    
    assertThrows(UnsupportedOperationException.class, retry::unsafeRunSync);
  }
  
  @Test
  void andThen(@Mock Consumer<String> console) {
    Schedule<Unit, Integer> two =
        Schedule.<Unit>recurs(1).andThen(Schedule.<Unit>recurs(1));

    IO<Unit> print = IO.exec(() -> console.accept("hola"));
    IO<Integer> repeat = print.repeat(two);
    
    Integer provide = repeat.unsafeRunSync();
    
    assertEquals(1, provide);
    verify(console, times(3)).accept("hola");
  }
  
  @Test
  @Disabled("I don't understand very well this")
  void compose(@Mock Consumer<String> console) {
    Schedule<Unit, Integer> two =
      Schedule.<Unit>recurs(1).compose(Schedule.<Integer>recurs(1));

    IO<Unit> print = IO.exec(() -> console.accept("hola"));
    IO<Integer> repeat = print.repeat(two);
    
    Integer provide = repeat.unsafeRunSync();
    
    assertEquals(Either.right(1), provide);
    verify(console, times(3)).accept("hola");
  }
  
  @Test
  void collect() {
    IO<Unit> pure = IO.unit();
    
    Schedule<Unit, Seq<Integer>> schedule = Schedule.<Unit>recurs(5).collectAll().zipLeft(Schedule.identity());
    IO<Seq<Integer>> repeat = pure.repeat(schedule);
    
    Seq<Integer> result = repeat.unsafeRunSync();
    
    assertEquals(List.of(0, 1, 2, 3, 4), result);
  }
}