/*
* Copyright 2012 LinkedIn, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.linkedin.parseq;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
/**
* @author Jaroslaw Odzga (jodzga@linkedin.com)
*/
public class TestTaskReuse extends BaseEngineTest {
@Test
public void testExecuteMultipleTimes() {
final AtomicInteger counter = new AtomicInteger();
Task<String> task = Task.callable(() -> {
counter.incrementAndGet();
return "hello";
} );
runAndWait("TestTaskReuse.testExecuteMultipleTimes-1", task);
runAndWait("TestTaskReuse.testExecuteMultipleTimes-2", task);
runAndWait("TestTaskReuse.testExecuteMultipleTimes-3", task);
assertEquals(counter.get(), 1);
}
/**
* In this case the "increaser" task is not being executed because
* the "bob" task has already been resolved and test1 task is
* resolved immediately.
*/
@Test
public void testLastTaskAlreadyResolved() {
final AtomicInteger counter = new AtomicInteger();
final Task<String> bob = Task.value("bob", "bob");
runAndWait("TestTaskReuse.testLastTaskResolved-bob", bob);
Task<String> task = Task.callable("increaser", () -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> test1 = task.andThen(bob);
runAndWait("TestTaskReuse.testLastTaskResolved", test1);
assertEquals(counter.get(), 0);
}
@Test
public void testLastTaskAlreadyResolvedShareable() {
final AtomicInteger counter = new AtomicInteger();
final Task<String> bob = Task.value("bob", "bob");
runAndWait("TestTaskReuse.testLastTaskAlreadyResolvedShareable-bob", bob);
Task<String> task = Task.callable("increaser", () -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> test1 = task.andThen(bob.shareable());
runAndWait("TestTaskReuse.testLastTaskAlreadyResolvedShareable", test1);
assertEquals(counter.get(), 1);
}
@Test
public void testShareableWithPar() {
final AtomicInteger counter = new AtomicInteger();
Task<String> task = Task.callable("increaser", () -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> test =
Task.par(task.shareable().map(x -> x + "1"), task.shareable().map(x -> x + "2")).map((a, b) -> a + b);
runAndWait("TestTaskReuse.testShareableWithPar", test);
assertEquals(counter.get(), 1);
assertEquals(test.get(), "hello1hello2");
}
@Test
public void testCancellationPar() {
Task<String> task = delayedValue("hello", 50, TimeUnit.MILLISECONDS);
Task<String> test1 =
Task.par(task, Task.failure(new RuntimeException("ups"))).map((a, b) -> a + b);
try {
runAndWait("TestTaskReuse.testCancellationPar-test1", test1);
fail("should have failed!");
} catch (Exception ex) {
assertTrue(test1.isFailed());
}
Task<String> test2 = Task.par(task.map("1", x -> x + "1"), task.map("2", x -> x + "2")).map((a, b) -> a + b);
try {
runAndWait("TestTaskReuse.testCancellationPar-test2", test2);
fail("should have failed!");
} catch (Exception ex) {
assertTrue(test2.isFailed());
}
}
@Test
public void testShareableCancellationPar() {
Task<String> task = delayedValue("hello", 50, TimeUnit.MILLISECONDS);
Task<String> test1 =
Task.par(task.shareable().map(x -> x + "1"), Task.failure(new RuntimeException("ups"))).map((a, b) -> a + b);
try {
runAndWait("TestTaskReuse.testShareableCancellationPar-test1", test1);
fail("should have failed!");
} catch (Exception ex) {
assertTrue(test1.isFailed());
}
Task<String> test2 =
Task.par(task.shareable().map("1", x -> x + "1"), task.shareable().map("2", x -> x + "2")).map((a, b) -> a + b);
runAndWait("TestTaskReuse.testShareableCancellationPar-test2", test2);
assertEquals(test2.get(), "hello1hello2");
}
@Test
public void testTaskReusedByTwoPlans() {
final AtomicInteger counter = new AtomicInteger();
Task<String> task = Task.callable(() -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> plan1 = task.map(s -> s + " on earth!");
Task<String> plan2 = task.map(s -> s + " on moon!");
runAndWait("TestTaskReuse.testTaskReusedByTwoPlans-plan1", plan1);
runAndWait("TestTaskReuse.testTaskReusedByTwoPlans-plan2", plan2);
assertEquals(counter.get(), 1);
assertEquals(countTasks(plan1.getTrace()), 3);
assertEquals(countTasks(plan2.getTrace()), 3);
}
@Test
public void testTaskReusedByTwoPlansAndMerged() {
final AtomicInteger counter = new AtomicInteger();
Task<String> task = Task.callable(() -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> plan1 = task.map(s -> s + " on earth!");
Task<String> plan2 = task.map(s -> s + " on moon!");
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMerged-plan1", plan1);
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMerged-plan2", plan2);
Task<Integer> length1 = plan1.map("length", s -> s.length());
Task<Integer> length2 = plan2.map("length", s -> s.length());
Task<Integer> merged = Task.par(length1, length2).map((a, b) -> a + b);
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMerged-merged", merged);
assertEquals(counter.get(), 1);
assertEquals(countTasks(merged.getTrace()), 10);
assertEquals(countTasks(plan1.getTrace()), 3);
assertEquals(countTasks(plan2.getTrace()), 3);
}
@Test
public void testTaskReusedByTwoPlansAndMergedWithFlatMap() {
final AtomicInteger counter = new AtomicInteger();
Task<String> task = Task.callable(() -> {
counter.incrementAndGet();
return "hello";
} );
Task<String> plan1 = task.flatMap("+earth", s -> Task.callable(() -> s + " on earth!"));
Task<String> plan2 = task.flatMap("+moon", s -> Task.callable(() -> s + " on moon!"));
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMergedWithFlatMap-plan1", plan1);
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMergedWithFlatMap-plan2", plan2);
Task<Integer> length1 = plan1.map("length", s -> s.length());
Task<Integer> length2 = plan2.map("length", s -> s.length());
Task<Integer> merged = Task.par(length1, length2).map((a, b) -> a + b);
runAndWait("TestTaskReuse.testTaskReusedByTwoPlansAndMergedWithFlatMap-merged", merged);
assertEquals(counter.get(), 1);
assertEquals(countTasks(merged.getTrace()), 9);
assertEquals(countTasks(plan1.getTrace()), 5);
assertEquals(countTasks(plan2.getTrace()), 5);
}
}