Skip to content

Commit

Permalink
(#1112) Speed up unit tests to max 10 secs
Browse files Browse the repository at this point in the history
* Speed up ThreadsTest by shortening sleep durations
  and reducing number of threads
* Stop recompiling all source files due to bug in
  maven-compiler-plugin
  • Loading branch information
llorllale committed Apr 23, 2019
1 parent 4a76741 commit eb13135
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 123 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ The MIT License (MIT)
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
Expand Down
196 changes: 74 additions & 122 deletions src/test/java/org/cactoos/experimental/ThreadsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,114 +24,62 @@

package org.cactoos.experimental;

import java.time.Duration;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.cactoos.Proc;
import org.cactoos.func.Repeated;
import org.cactoos.func.Timed;
import org.cactoos.func.UncheckedFunc;
import org.cactoos.list.ListOf;
import org.cactoos.list.Mapped;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsEqual;
import org.junit.Test;
import org.llorllale.cactoos.matchers.Assertion;
import org.llorllale.cactoos.matchers.HasValues;
import org.llorllale.cactoos.matchers.Throws;

/**
* Test case for {@link Threads}.
*
* @since 1.0.0
* @checkstyle MagicNumberCheck (500 lines)
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
* @todo #1112:30min Continue speeding up the `mvn test` goal until it
* executes in less than 10 seconds, or as fast as reasonably possible.
*/
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
public final class ThreadsTest {

/**
* Example of JDK8 way for handling of concurrent tasks.
* This code base should be simplified.
*/
@Test(timeout = 10000)
public void oldSchoolWay() {
final ExecutorService extor = Executors.newFixedThreadPool(5);
try {
final Collection<Future<String>> futures = extor.invokeAll(
new ListOf<Callable<String>>(
() -> {
TimeUnit.SECONDS.sleep(2);
return "1st";
},
() -> {
TimeUnit.SECONDS.sleep(6);
return "3rd";
},
() -> {
TimeUnit.SECONDS.sleep(4);
return "2nd";
}
)
);
MatcherAssert.assertThat(
new Mapped<>(Future::get, futures),
Matchers.hasItems("1st", "3rd", "2nd")
);
} catch (final InterruptedException exp) {
Thread.currentThread().interrupt();
throw new IllegalStateException(exp);
} finally {
try {
extor.shutdown();
if (!extor.awaitTermination(2, TimeUnit.SECONDS)) {
extor.shutdownNow();
}
} catch (final InterruptedException exp) {
extor.shutdownNow();
}
}
}

/**
* Execute the tasks concurrently using {@link Threads} when
* {@link ExecutorService} was initiated by someone else.
*/
@Test
public void cactoosWay() {
this.repeatWithTimeout(
public void containsResults() {
this.repeat(
arg -> {
final ExecutorService extor = Executors.newFixedThreadPool(3);
try {
MatcherAssert.assertThat(
new Threads<String>(
new Assertion<>(
"contains results from callables",
() -> new Threads<String>(
extor,
() -> {
TimeUnit.SECONDS.sleep(3);
this.sleep();
return "txt 1";
},
() -> {
TimeUnit.SECONDS.sleep(3);
this.sleep();
return "txt 2";
},
() -> {
TimeUnit.SECONDS.sleep(3);
this.sleep();
return "txt 3";
}
),
new HasValues<>("txt 1", "txt 2", "txt 3")
);
).affirm();
} finally {
try {
extor.shutdown();
if (!extor.awaitTermination(1, TimeUnit.SECONDS)) {
extor.shutdownNow();
}
} catch (final InterruptedException exp) {
extor.shutdown();
if (!extor.awaitTermination(1L, TimeUnit.SECONDS)) {
extor.shutdownNow();
}
}
Expand All @@ -143,73 +91,77 @@ public void cactoosWay() {
* Execute 1 task within executor service and ensure that we'll get the
* expected exception type.
*/
@Test(expected = CompletionException.class)
public void executionIsFailedDueToException() {
new Threads<String>(
Executors.newSingleThreadExecutor(),
() -> {
throw new IllegalStateException("Something went wrong");
}
).iterator().next();
@Test
public void failsDueToException() {
new Assertion<>(
"wraps error into CompletionException",
() -> new Threads<String>(
Executors.newSingleThreadExecutor(),
() -> {
throw new IllegalStateException("Something went wrong");
}
).iterator().next(),
new Throws<>(
"java.lang.IllegalStateException: Something went wrong",
CompletionException.class
)
).affirm();
}

/**
* Execute the tasks concurrently using {@link Threads} when
* {@link ExecutorService} was initiated by {@link Threads} itself.
*/
@Test
public void cactoosWayWithInlineExecutorService() {
this.repeatWithTimeout(
arg -> {
MatcherAssert.assertThat(
new Threads<String>(
5,
() -> {
TimeUnit.SECONDS.sleep(3);
return "txt 1";
},
() -> {
TimeUnit.SECONDS.sleep(3);
return "txt 2";
},
() -> {
TimeUnit.SECONDS.sleep(3);
return "txt 3";
},
() -> {
TimeUnit.SECONDS.sleep(3);
return "txt 4";
},
() -> {
TimeUnit.SECONDS.sleep(3);
return "txt 5";
}
),
new HasValues<>("txt 1", "txt 2", "txt 3", "txt 4", "txt 5")
);
}
public void containsValuesWithInlineExecutorService() {
this.repeat(
arg -> new Assertion<>(
// @checkstyle LineLength (1 line)
"contains results from the callables when using the inline executor service",
() -> new Threads<String>(
3,
() -> {
this.sleep();
return "txt 1";
},
() -> {
this.sleep();
return "txt 2";
},
() -> {
this.sleep();
return "txt 3";
}
),
new HasValues<>("txt 1", "txt 2", "txt 3")
).affirm()
);
}

/**
* Execute the test at least 10 times with timeout in 5 seconds each.
* Repeat the test several times.
* @param test The test to execute.
*/
private void repeatWithTimeout(final Proc<?> test) {
MatcherAssert.assertThat(
new UncheckedFunc<>(
new Repeated<>(
new Timed<Boolean, Boolean>(
input -> {
test.exec(null);
return true;
},
Duration.ofSeconds(5).toMillis()
),
10
)
).apply(true),
new IsEqual<>(true)
);
private void repeat(final Proc<?> test) {
new UncheckedFunc<>(
new Repeated<>(
arg -> {
test.exec(null);
return null;
},
5
)
).apply(Boolean.TRUE);
}

/**
* Sleep.
*/
private void sleep() {
try {
TimeUnit.MILLISECONDS.sleep(100L);
} catch (final InterruptedException iex) {
throw new IllegalStateException(iex);
}
}
}

1 comment on commit eb13135

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on eb13135 Apr 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 1112-aa9105a7 discovered in src/test/java/org/cactoos/experimental/ThreadsTest.java and submitted as #1115. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.