Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: migrate ParallelProcessorTest to JUnit 5 #4543

Merged
merged 2 commits into from
Jan 22, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,29 @@
* Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon.
*/
package spoon.test.processing.processors;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import spoon.FluentLauncher;
import spoon.SpoonException;
import spoon.processing.AbstractParallelProcessor;
import spoon.processing.AbstractProcessor;
import spoon.processing.Processor;
import spoon.reflect.declaration.CtElement;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.stream.IntStream;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import spoon.FluentLauncher;
import spoon.SpoonException;
import spoon.processing.AbstractParallelProcessor;
import spoon.processing.AbstractProcessor;
import spoon.processing.Processor;
import spoon.reflect.declaration.CtElement;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ParallelProcessorTest {
private static final String INPUT_FILES = "src/test/resources/deprecated/input";
@Rule
public TemporaryFolder folderFactory = new TemporaryFolder();

private AtomicReferenceArray<Integer> createCounter() {
Integer[] counter = new Integer[] { 0, 0, 0, 0 };
AtomicReferenceArray<Integer> atomicCounter = new AtomicReferenceArray<Integer>(counter);
Expand All @@ -52,7 +46,7 @@ public void process(CtElement element) {
}

@Test
public void compareWithSingleThreaded1() throws IOException {
public void compareWithSingleThreaded1(@TempDir Path outputFolder) throws IOException {
// contract: running with 4 processors parallel must produce the same result as
// single threaded processor.
// for testing this a simple processor counting visited nodes is used.
Expand All @@ -69,7 +63,7 @@ public void compareWithSingleThreaded1() throws IOException {
.processor(new AbstractParallelProcessor<CtElement>(Arrays.asList(p1, p2, p3, p4)) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel();

AtomicInteger singleThreadCounter = new AtomicInteger(0);
Expand All @@ -78,15 +72,15 @@ public void compareWithSingleThreaded1() throws IOException {
public void process(CtElement element) {
singleThreadCounter.incrementAndGet();
}
}).noClasspath(true).outputDirectory(folderFactory.newFolder()).buildModel();
}).noClasspath(true).outputDirectory(outputFolder.toFile()).buildModel();

int sequentialCount = singleThreadCounter.get();
int parallelCount = IntStream.range(0, atomicCounter.length()).map(atomicCounter::get).sum();
assertThat(parallelCount, equalTo(sequentialCount));
}

@Test
public void compareWithSingleThreaded2() throws IOException {
public void compareWithSingleThreaded2(@TempDir Path outputFolder) throws IOException {
// contract: a parallelProcessor with one thread must produce the same result as
// a normal processor.

Expand All @@ -97,45 +91,45 @@ public void compareWithSingleThreaded2() throws IOException {
.processor(new AbstractParallelProcessor<CtElement>(Arrays.asList(p1)) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel();
AtomicInteger singleThreadCounter = new AtomicInteger(0);
new FluentLauncher().inputResource(INPUT_FILES).processor(new AbstractProcessor<CtElement>() {
@Override
public void process(CtElement element) {
singleThreadCounter.incrementAndGet();
}
}).noClasspath(true).outputDirectory(folderFactory.newFolder()).buildModel();
}).noClasspath(true).outputDirectory(outputFolder.toFile()).buildModel();

assertThat(atomicCounter.get(0), equalTo(singleThreadCounter.get()));
}

@Test
public void consumerConstructorTest() throws IOException {
public void consumerConstructorTest(@TempDir Path outputFolder) throws IOException {
// contract: creating with consumer constructor must produces correct results.
// See other tests for explanation how the testing works.
AtomicReferenceArray<Integer> atomicCounter = createCounter();
new FluentLauncher().inputResource(INPUT_FILES)
.processor(new AbstractParallelProcessor<CtElement>((e) -> atomicCounter.getAndUpdate(0, i -> i + 1), 4) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel();
AtomicInteger singleThreadCounter = new AtomicInteger(0);
new FluentLauncher().inputResource(INPUT_FILES).processor(new AbstractProcessor<CtElement>() {
@Override
public void process(CtElement element) {
singleThreadCounter.incrementAndGet();
}
}).noClasspath(true).outputDirectory(folderFactory.newFolder()).buildModel();
}).noClasspath(true).outputDirectory(outputFolder.toFile()).buildModel();

int sequentialCount = singleThreadCounter.get();
int parallelCount = IntStream.range(0, atomicCounter.length()).map(atomicCounter::get).sum();
assertThat(parallelCount, equalTo(sequentialCount));
}

@Test
public void compareWithSingleThreaded3() throws IOException {
public void compareWithSingleThreaded3(@TempDir Path outputFolder) throws IOException {
// contract: using an iterable with more elements than used should only use the
// given number. Result must be correct too.
// Here the iterable<Processor> has size 4 and only 3 are used.
Expand All @@ -150,15 +144,15 @@ public void compareWithSingleThreaded3() throws IOException {
.processor(new AbstractParallelProcessor<CtElement>(Arrays.asList(p1, p2, p3, p4), 3) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel();
AtomicInteger singleThreadCounter = new AtomicInteger(0);
new FluentLauncher().inputResource(INPUT_FILES).processor(new AbstractProcessor<CtElement>() {
@Override
public void process(CtElement element) {
singleThreadCounter.incrementAndGet();
}
}).noClasspath(true).outputDirectory(folderFactory.newFolder()).buildModel();
}).noClasspath(true).outputDirectory(outputFolder.toFile()).buildModel();


int sequentialCount = singleThreadCounter.get();
Expand All @@ -168,7 +162,7 @@ public void process(CtElement element) {
}

@Test
public void testSize() throws IOException {
public void testSize(@TempDir Path outputFolder) throws IOException {
// contract: a thread pool with size zero must not created.
AtomicReferenceArray<Integer> atomicCounter = createCounter();
Processor<CtElement> p1 = createProcessor(atomicCounter, 0);
Expand All @@ -177,56 +171,56 @@ public void testSize() throws IOException {
.processor(new AbstractParallelProcessor<CtElement>(Arrays.asList(p1), 0) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel());
}

@Test
public void testSize2() throws IOException {
public void testSize2(@TempDir Path outputFolder) throws IOException {
// contract: negative processor numbers must throw an exception.
AtomicReferenceArray<Integer> atomicCounter = createCounter();
Processor<CtElement> p1 = createProcessor(atomicCounter, 0);
assertThrows(IllegalArgumentException.class, () -> new FluentLauncher().inputResource(INPUT_FILES)
.processor(new AbstractParallelProcessor<CtElement>(Arrays.asList(p1), -5) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel());
}

@Test
public void testSize3() throws IOException {
public void testSize3(@TempDir Path outputFolder) throws IOException {
// contract: trying to consume more processor than provided must throw an
// exception.
assertThrows(SpoonException.class, () -> new FluentLauncher().inputResource(INPUT_FILES)
.processor(new AbstractParallelProcessor<CtElement>(Collections.emptyList(), 1) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel());
}

@Test
public void testSize4() throws IOException {
public void testSize4(@TempDir Path outputFolder) throws IOException {
// contract: trying to consume more processor than provided must throw an
// exception.
assertThrows(IllegalArgumentException.class, () -> new FluentLauncher().inputResource(INPUT_FILES)
.processor(new AbstractParallelProcessor<CtElement>(Collections.emptyList()) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel());
}

@Test
public void testSize5() throws IOException {
public void testSize5(@TempDir Path outputFolder) throws IOException {
// contract: a thread pool with size zero must not created.

assertThrows(IllegalArgumentException.class, () -> new FluentLauncher().inputResource(INPUT_FILES)
.processor(new AbstractParallelProcessor<CtElement>((v) -> v.toString(), 0) {
})
.noClasspath(true)
.outputDirectory(folderFactory.newFolder())
.outputDirectory(outputFolder.toFile())
.buildModel());
}

Expand Down