<commit_before>package com.github.javactic.futures;

import com.github.javactic.Bad;
import com.github.javactic.Every;
import com.github.javactic.Fail;
import com.github.javactic.Good;
import com.github.javactic.One;
import com.github.javactic.Or;
import com.github.javactic.Pass;
import com.github.javactic.Validation;
import javaslang.collection.Seq;
import javaslang.collection.Vector;
import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.time.Duration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


//@RunWith(Theories.class)
public class AccumulationTest {
  private FutureFactory<String> ff = FutureFactory.OF_EXCEPTION_MESSAGE;
  private FutureFactory<One<String>> ffAcc = ff.accumulating();

//  @DataPoints
  public static ExecutorService[] configs = {ForkJoinPool.commonPool()};

  @Test
  public void withGoodFail() throws Exception {
    OrFuture<String, One<String>> success = OrFuture.ofGood("success");
    OrFuture<String, One<String>> fail = OrFuture.ofOneBad("failure");
    OrFuture<String, Every<String>> result = OrFuture.withGood(success, fail, (a1, a2) -> "doesn't matter");
    Or<String, Every<String>> or = result.get(Duration.ofSeconds(10));
    assertEquals("failure", or.getBad().head());
  }

  @Test
  public void withGoodSuccess() throws Exception {
    OrFuture<String, One<String>> s1 = OrFuture.ofGood("A");
    OrFuture<Integer, One<String>> s2 = OrFuture.ofGood(1);
    OrFuture<String, Every<String>> result = OrFuture.withGood(s1, s2, (a1, a2) -> a1 + a2);
    Or<String, Every<String>> or = result.get(Duration.ofSeconds(10));
    assertEquals("A1", or.get());
  }

//  @Theory
  @Test
  public void sequenceSuccess() throws Exception {
    Seq<OrFuture<Integer, One<String>>> seq = Vector.empty();
    for (int i = 0; i < 10; i++) {
      final int fi = i;
//      seq = seq.append(ff.newFuture(es, () -> Good.of(fi)).accumulating());
      seq = seq.append(ff.newFuture(() -> Good.of(fi)).accumulating());
    }
    OrFuture<Vector<Integer>, Every<String>> sequence = OrFuture.combined(seq);
    Or<Vector<Integer>, Every<String>> or = sequence.get(Duration.ofSeconds(10));
    Assert.assertTrue(or.isGood());
    String fold = or.get().foldLeft("", (s, i) -> s + i);
    assertEquals("0123456789", fold);
  }

//  @Theory
  @Test
  public void sequenceFailure() throws Exception {
    Seq<OrFuture<Integer, One<String>>> seq = Vector.empty();
    for (int i = 0; i < 10; i++) {
      final int fi = i;
//      if (i % 2 == 0)
//        seq = seq.append(ffAcc.newFuture(es, () -> Good.of(fi)));
//      else
//        seq = seq.append(ffAcc.newFuture(es, () -> Bad.ofOne(fi+ "")));
      if (i % 2 == 0)
        seq = seq.append(ffAcc.newFuture(() -> Good.of(fi)));
      else
        seq = seq.append(ffAcc.newFuture(() -> Bad.ofOne(fi+ "")));
    }
    OrFuture<Vector<Integer>, Every<String>> sequence = OrFuture.combined(seq);
    Or<Vector<Integer>, Every<String>> or = sequence.get(Duration.ofSeconds(10));
    Assert.assertTrue(or.isBad());
    String fold = or.getBad().foldLeft("", (s, i) -> s + i);
    assertEquals("13579", fold);
  }

//  @Test
//  public void combinedSecondFinishesFirst() throws Exception {
//    CountDownLatch latch = new CountDownLatch(1);
//    OrFuture<String, String> f1 = ff.newFuture(() -> {
//      try {
//        latch.await();
//      } catch (Exception e) {
//        Assert.fail();
//      }
//      return Good.of("1");
//    });
//    OrFuture<String, String> f2 = ff.newFuture(() -> Good.of("2"));
//    OrFuture<Vector<String>, Every<String>> combined = OrFuture.combined(Vector.of(f1.accumulating(), f2.accumulating()));
//    f2.onComplete(or -> latch.countDown());
//    Or<Vector<String>, Every<String>> or = combined.get(Duration.ofSeconds(10));
//    Assert.assertTrue(or.isGood());
//    String fold = or.get().foldLeft("", (s, i) -> s + i);
//    assertEquals("12", fold);
//  }
//
//  @Test
//  public void combinedSecondFinishesLast() throws Exception {
//    CountDownLatch latch = new CountDownLatch(1);
//    OrFuture<String, String> f1 = ff.newFuture(() -> Good.of("1"));
//    OrFuture<String, String> f2 = ff.newFuture(() -> {
//      try {
//        latch.await();
//      } catch (Exception e) {
//        Assert.fail();
//      }
//      return Good.of("2");
//    });
//    OrFuture<Vector<String>, Every<String>> combined = OrFuture.combined(Vector.of(f1.accumulating(), f2.accumulating()));
//    f1.onComplete(or -> latch.countDown());
//    Or<Vector<String>, Every<String>> or = combined.get(Duration.ofSeconds(10));
//    Assert.assertTrue(or.isGood());
//    String fold = or.get().foldLeft("", (s, i) -> s + i);
//    assertEquals("12", fold);
//  }

//  @Theory
  @Test
  public void validatedBy() throws InterruptedException, ExecutionException, TimeoutException {
    Vector<Integer> vec = Vector.of(1,2,3);
    Function<Integer, OrFuture<Integer, One<String>>> f = i ->
      ffAcc.newFuture(() -> {
        if(i < 10) return Good.of(i);
        else return Bad.ofOne("wasn't under 10");
      });
    Or<Vector<Integer>, Every<String>> res = OrFuture.validatedBy(vec, f).get(Duration.ofSeconds(10));
    assertTrue(res.isGood());
    assertEquals(vec, res.get());
    res = OrFuture.validatedBy(Vector.of(11), f, Vector.collector()).get(Duration.ofSeconds(10));
    assertTrue(res.isBad());
    assertTrue(res.getBad() instanceof One);
  }

//  @Theory
  @Test
  public void when() throws InterruptedException, ExecutionException, TimeoutException {
    Function<String, Validation<String>> f1 = f -> f.startsWith("s") ? Pass.instance() : Fail.of("does not start with s");
    Function<String, Validation<String>> f2 = f -> f.length() > 4 ? Fail.of("too long") : Pass.instance();
    OrFuture<String, One<String>> orFuture = ff.newFuture(() -> Bad.<String,String>of("failure")).accumulating();
    OrFuture<String, Every<String>> res = OrFuture.when(orFuture, f1, f2);
    assertEquals("failure", res.get(Duration.ofSeconds(10)).getBad().get(0));
    orFuture = ff.newFuture(() -> Good.of("sub")).accumulating();
    res = OrFuture.when(orFuture, f1, f2);
    assertTrue(res.get(Duration.ofSeconds(10)).isGood());
    orFuture = ff.newFuture(() -> Good.of("fubiluuri")).accumulating();
    res = OrFuture.when(orFuture, f1, f2);
    assertTrue(res.get(Duration.ofSeconds(10)).isBad());
  }

//  @Theory
  @Test
  public void withGood() throws Exception {
    ExecutorService es = ForkJoinPool.commonPool();
    Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> fun =
      ors -> OrFuture.withGood(ors[0], ors[1], (a, b) -> "");
    testWithF(es, fun, 2);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], (a, b, c) -> "");
    testWithF(es, fun, 3);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], (a, b, c, d) -> "");
    testWithF(es, fun, 4);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], (a, b, c, d, e) -> "");
    testWithF(es, fun, 5);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], (a, b, c, d, e, f) -> "");
    testWithF(es, fun, 6);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], o[6], (a, b, c, d, e, f, g) -> "");
    testWithF(es, fun, 7);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7], (a, b, c, d, e, f, g, h) -> "");
    testWithF(es, fun, 8);
  }

//  @Theory
  @Test
  public void zips() throws Exception {
    ExecutorService es = ForkJoinPool.commonPool();
    Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> fun =
      ors -> OrFuture.zip(ors[0], ors[1]);
    testWithF(es, fun, 2);
    fun = o -> OrFuture.zip3(o[0], o[1], o[2]);
    testWithF(es, fun, 3);
  }

  private void testWithF(ExecutorService es,
                         Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> f,
                         int size) throws Exception {
    @SuppressWarnings("unchecked")
    OrFuture<String, One<String>>[] ors = new OrFuture[size];
    for (int i = 0; i <= ors.length; i++) {
      for (int j = 0; j < ors.length; j++) {
        if (j == i) ors[j] = ff.newFuture(es, () -> Bad.<String,String>of("failure")).accumulating();
        else ors[j] = ffAcc.newFuture(es, () -> Good.of("success"));
      }
      OrFuture<?, Every<String>> val = f.apply(ors);
      if (i < ors.length)
        assertTrue(val.get(Duration.ofSeconds(10)).isBad());
      else<commit_msg>debug concurrent test problems<commit_after>package com.github.javactic.futures;

import com.github.javactic.Bad;
import com.github.javactic.Every;
import com.github.javactic.Fail;
import com.github.javactic.Good;
import com.github.javactic.One;
import com.github.javactic.Or;
import com.github.javactic.Pass;
import com.github.javactic.Validation;
import javaslang.collection.Seq;
import javaslang.collection.Vector;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.time.Duration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


@RunWith(Theories.class)
public class AccumulationTest {
  private FutureFactory<String> ff = FutureFactory.OF_EXCEPTION_MESSAGE;
  private FutureFactory<One<String>> ffAcc = ff.accumulating();

  @DataPoints
  public static ExecutorService[] configs = {Executors.newSingleThreadExecutor(), ForkJoinPool.commonPool()};

  @Test
  public void withGoodFail() throws Exception {
    OrFuture<String, One<String>> success = OrFuture.ofGood("success");
    OrFuture<String, One<String>> fail = OrFuture.ofOneBad("failure");
    OrFuture<String, Every<String>> result = OrFuture.withGood(success, fail, (a1, a2) -> "doesn't matter");
    Or<String, Every<String>> or = result.get(Duration.ofSeconds(10));
    assertEquals("failure", or.getBad().head());
  }

  @Test
  public void withGoodSuccess() throws Exception {
    OrFuture<String, One<String>> s1 = OrFuture.ofGood("A");
    OrFuture<Integer, One<String>> s2 = OrFuture.ofGood(1);
    OrFuture<String, Every<String>> result = OrFuture.withGood(s1, s2, (a1, a2) -> a1 + a2);
    Or<String, Every<String>> or = result.get(Duration.ofSeconds(10));
    assertEquals("A1", or.get());
  }

  @Theory
  public void sequenceSuccess(ExecutorService es) throws Exception {
    Seq<OrFuture<Integer, One<String>>> seq = Vector.empty();
    for (int i = 0; i < 10; i++) {
      final int fi = i;
      seq = seq.append(ff.newFuture(es, () -> Good.of(fi)).accumulating());
    }
    OrFuture<Vector<Integer>, Every<String>> sequence = OrFuture.combined(seq);
    Or<Vector<Integer>, Every<String>> or = sequence.get(Duration.ofSeconds(10));
    Assert.assertTrue(or.isGood());
    String fold = or.get().foldLeft("", (s, i) -> s + i);
    assertEquals("0123456789", fold);
  }

  @Theory
  public void sequenceFailure(ExecutorService es) throws Exception {
    Seq<OrFuture<Integer, One<String>>> seq = Vector.empty();
    for (int i = 0; i < 10; i++) {
      final int fi = i;
      if (i % 2 == 0)
        seq = seq.append(ffAcc.newFuture(es, () -> Good.of(fi)));
      else
        seq = seq.append(ffAcc.newFuture(es, () -> Bad.ofOne(fi+ "")));
    }
    OrFuture<Vector<Integer>, Every<String>> sequence = OrFuture.combined(seq);
    Or<Vector<Integer>, Every<String>> or = sequence.get(Duration.ofSeconds(10));
    Assert.assertTrue(or.isBad());
    String fold = or.getBad().foldLeft("", (s, i) -> s + i);
    assertEquals("13579", fold);
  }

//  @Test
//  public void combinedSecondFinishesFirst() throws Exception {
//    CountDownLatch latch = new CountDownLatch(1);
//    OrFuture<String, String> f1 = ff.newFuture(() -> {
//      try {
//        latch.await();
//      } catch (Exception e) {
//        Assert.fail();
//      }
//      return Good.of("1");
//    });
//    OrFuture<String, String> f2 = ff.newFuture(() -> Good.of("2"));
//    OrFuture<Vector<String>, Every<String>> combined = OrFuture.combined(Vector.of(f1.accumulating(), f2.accumulating()));
//    f2.onComplete(or -> latch.countDown());
//    Or<Vector<String>, Every<String>> or = combined.get(Duration.ofSeconds(10));
//    Assert.assertTrue(or.isGood());
//    String fold = or.get().foldLeft("", (s, i) -> s + i);
//    assertEquals("12", fold);
//  }
//
//  @Test
//  public void combinedSecondFinishesLast() throws Exception {
//    CountDownLatch latch = new CountDownLatch(1);
//    OrFuture<String, String> f1 = ff.newFuture(() -> Good.of("1"));
//    OrFuture<String, String> f2 = ff.newFuture(() -> {
//      try {
//        latch.await();
//      } catch (Exception e) {
//        Assert.fail();
//      }
//      return Good.of("2");
//    });
//    OrFuture<Vector<String>, Every<String>> combined = OrFuture.combined(Vector.of(f1.accumulating(), f2.accumulating()));
//    f1.onComplete(or -> latch.countDown());
//    Or<Vector<String>, Every<String>> or = combined.get(Duration.ofSeconds(10));
//    Assert.assertTrue(or.isGood());
//    String fold = or.get().foldLeft("", (s, i) -> s + i);
//    assertEquals("12", fold);
//  }

  @Theory
  public void validatedBy(ExecutorService es) throws InterruptedException, ExecutionException, TimeoutException {
    Vector<Integer> vec = Vector.of(1,2,3);
    Function<Integer, OrFuture<Integer, One<String>>> f = i ->
      ffAcc.newFuture(es, () -> {
        if(i < 10) return Good.of(i);
        else return Bad.ofOne("wasn't under 10");
      });
    Or<Vector<Integer>, Every<String>> res = OrFuture.validatedBy(vec, f).get(Duration.ofSeconds(10));
    assertTrue(res.isGood());
    assertEquals(vec, res.get());
    res = OrFuture.validatedBy(Vector.of(11), f, Vector.collector()).get(Duration.ofSeconds(10));
    assertTrue(res.isBad());
    assertTrue(res.getBad() instanceof One);
  }

  @Theory
  public void when(ExecutorService es) throws InterruptedException, ExecutionException, TimeoutException {
    Function<String, Validation<String>> f1 = f -> f.startsWith("s") ? Pass.instance() : Fail.of("does not start with s");
    Function<String, Validation<String>> f2 = f -> f.length() > 4 ? Fail.of("too long") : Pass.instance();
    OrFuture<String, One<String>> orFuture = ff.newFuture(es, () -> Bad.<String,String>of("failure")).accumulating();
    OrFuture<String, Every<String>> res = OrFuture.when(orFuture, f1, f2);
    assertEquals("failure", res.get(Duration.ofSeconds(10)).getBad().get(0));
    orFuture = ff.newFuture(es, () -> Good.of("sub")).accumulating();
    res = OrFuture.when(orFuture, f1, f2);
    assertTrue(res.get(Duration.ofSeconds(10)).isGood());
    orFuture = ff.newFuture(es, () -> Good.of("fubiluuri")).accumulating();
    res = OrFuture.when(orFuture, f1, f2);
    assertTrue(res.get(Duration.ofSeconds(10)).isBad());
  }

  @Theory
  public void withGood(ExecutorService es) throws Exception {
    Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> fun =
      ors -> OrFuture.withGood(ors[0], ors[1], (a, b) -> "");
    testWithF(es, fun, 2);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], (a, b, c) -> "");
    testWithF(es, fun, 3);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], (a, b, c, d) -> "");
    testWithF(es, fun, 4);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], (a, b, c, d, e) -> "");
    testWithF(es, fun, 5);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], (a, b, c, d, e, f) -> "");
    testWithF(es, fun, 6);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], o[6], (a, b, c, d, e, f, g) -> "");
    testWithF(es, fun, 7);
    fun = o -> OrFuture.withGood(o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7], (a, b, c, d, e, f, g, h) -> "");
    testWithF(es, fun, 8);
  }

  @Theory
  public void zips(ExecutorService es) throws Exception {
    Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> fun =
      ors -> OrFuture.zip(ors[0], ors[1]);
    testWithF(es, fun, 2);
    fun = o -> OrFuture.zip3(o[0], o[1], o[2]);
    testWithF(es, fun, 3);
  }

  private void testWithF(ExecutorService es,
                         Function<? super OrFuture<String, ? extends Every<String>>[], OrFuture<?, Every<String>>> f,
                         int size) throws Exception {
    @SuppressWarnings("unchecked")
    OrFuture<String, One<String>>[] ors = new OrFuture[size];
    for (int i = 0; i <= ors.length; i++) {
      for (int j = 0; j < ors.length; j++) {
        if (j == i) ors[j] = ff.newFuture(es, () -> Bad.<String,String>of("failure")).accumulating();
        else ors[j] = ffAcc.newFuture(es, () -> Good.of("success"));
      }
      OrFuture<?, Every<String>> val = f.apply(ors);
      if (i < ors.length)
        assertTrue(val.get(Duration.ofSeconds(10)).isBad());
      else
{'fraction_non_alphanumeric': 0.19078272758345677, 'fraction_numerical': 0.017204056055599864, 'mean_word_length': 3.5979570455735987, 'pattern_counts': {'":': 0, '<': 193, '<?xml version=': 0, '>': 266, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1371945', 'n_tokens_mistral': 6123, 'n_tokens_neox': 5974, 'n_words': 1269}