Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3753 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
1 changed files with 178 additions and 161 deletions
@ -1,161 +1,178 @@ |
|||||||
package org.springframework.scheduling; |
/* |
||||||
|
* Copyright 2002-2010 the original author or authors. |
||||||
import java.util.concurrent.Callable; |
* |
||||||
import java.util.concurrent.ExecutionException; |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
import java.util.concurrent.Future; |
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
import junit.framework.Assert; |
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
import static junit.framework.Assert.*; |
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
import org.junit.Before; |
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
import org.junit.Test; |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
import org.springframework.core.task.SimpleAsyncTaskExecutor; |
* See the License for the specific language governing permissions and |
||||||
import org.springframework.scheduling.annotation.Async; |
* limitations under the License. |
||||||
import org.springframework.scheduling.annotation.AsyncResult; |
*/ |
||||||
|
|
||||||
/** |
package org.springframework.scheduling.aspectj; |
||||||
* Test for AnnotationDrivenAsynchronousExecutionAspect |
|
||||||
* |
import java.util.concurrent.Callable; |
||||||
* @author Ramnivas Laddad |
import java.util.concurrent.ExecutionException; |
||||||
*/ |
import java.util.concurrent.Future; |
||||||
public class AnnotationDrivenAsynchronousExecutionAspectTest { |
|
||||||
private static final long WAIT_TIME = 1000; //milli seconds
|
import junit.framework.Assert; |
||||||
private CountingExecutor executor; |
|
||||||
|
import static junit.framework.Assert.*; |
||||||
@Before |
|
||||||
public void setUp() { |
import org.junit.Before; |
||||||
executor = new CountingExecutor(); |
import org.junit.Test; |
||||||
AnnotationDrivenAsynchronousExecutionAspect.aspectOf().setExecutor(executor); |
import org.springframework.core.task.SimpleAsyncTaskExecutor; |
||||||
} |
import org.springframework.scheduling.annotation.Async; |
||||||
|
import org.springframework.scheduling.annotation.AsyncResult; |
||||||
@Test |
|
||||||
public void asyncMethodGetsRoutedAsynchronously() { |
/** |
||||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
* @author Ramnivas Laddad |
||||||
obj.incrementAsync(); |
*/ |
||||||
executor.waitForCompletion(); |
public class AnnotationDrivenAsynchronousExecutionAspectTests { |
||||||
assertEquals(1, obj.counter); |
|
||||||
assertEquals(1, executor.submitStartCounter); |
private static final long WAIT_TIME = 1000; //milli seconds
|
||||||
assertEquals(1, executor.submitCompleteCounter); |
|
||||||
} |
private CountingExecutor executor; |
||||||
|
|
||||||
@Test |
@Before |
||||||
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { |
public void setUp() { |
||||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
executor = new CountingExecutor(); |
||||||
Future<Integer> future = obj.incrementReturningAFuture(); |
AnnotationDrivenAsynchronousExecutionAspect.aspectOf().setExecutor(executor); |
||||||
// No need to executor.waitForCompletion() as future.get() will have the same effect
|
} |
||||||
assertEquals(5, future.get().intValue()); |
|
||||||
assertEquals(1, obj.counter); |
@Test |
||||||
assertEquals(1, executor.submitStartCounter); |
public void asyncMethodGetsRoutedAsynchronously() { |
||||||
assertEquals(1, executor.submitCompleteCounter); |
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
||||||
} |
obj.incrementAsync(); |
||||||
|
executor.waitForCompletion(); |
||||||
@Test |
assertEquals(1, obj.counter); |
||||||
public void syncMethodGetsRoutedSynchronously() { |
assertEquals(1, executor.submitStartCounter); |
||||||
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
assertEquals(1, executor.submitCompleteCounter); |
||||||
obj.increment(); |
} |
||||||
assertEquals(1, obj.counter); |
|
||||||
assertEquals(0, executor.submitStartCounter); |
@Test |
||||||
assertEquals(0, executor.submitCompleteCounter); |
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { |
||||||
} |
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
||||||
|
Future<Integer> future = obj.incrementReturningAFuture(); |
||||||
@Test |
// No need to executor.waitForCompletion() as future.get() will have the same effect
|
||||||
public void voidMethodInAsyncClassGetsRoutedAsynchronously() { |
assertEquals(5, future.get().intValue()); |
||||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
assertEquals(1, obj.counter); |
||||||
obj.increment(); |
assertEquals(1, executor.submitStartCounter); |
||||||
executor.waitForCompletion(); |
assertEquals(1, executor.submitCompleteCounter); |
||||||
assertEquals(1, obj.counter); |
} |
||||||
assertEquals(1, executor.submitStartCounter); |
|
||||||
assertEquals(1, executor.submitCompleteCounter); |
@Test |
||||||
} |
public void syncMethodGetsRoutedSynchronously() { |
||||||
|
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation(); |
||||||
@Test |
obj.increment(); |
||||||
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { |
assertEquals(1, obj.counter); |
||||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
assertEquals(0, executor.submitStartCounter); |
||||||
Future<Integer> future = obj.incrementReturningAFuture(); |
assertEquals(0, executor.submitCompleteCounter); |
||||||
assertEquals(5, future.get().intValue()); |
} |
||||||
assertEquals(1, obj.counter); |
|
||||||
assertEquals(1, executor.submitStartCounter); |
@Test |
||||||
assertEquals(1, executor.submitCompleteCounter); |
public void voidMethodInAsyncClassGetsRoutedAsynchronously() { |
||||||
} |
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
||||||
|
obj.increment(); |
||||||
@Test |
executor.waitForCompletion(); |
||||||
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() { |
assertEquals(1, obj.counter); |
||||||
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
assertEquals(1, executor.submitStartCounter); |
||||||
int returnValue = obj.return5(); |
assertEquals(1, executor.submitCompleteCounter); |
||||||
assertEquals(5, returnValue); |
} |
||||||
assertEquals(0, executor.submitStartCounter); |
|
||||||
assertEquals(0, executor.submitCompleteCounter); |
@Test |
||||||
} |
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException { |
||||||
|
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
||||||
@SuppressWarnings("serial") |
Future<Integer> future = obj.incrementReturningAFuture(); |
||||||
private static class CountingExecutor extends SimpleAsyncTaskExecutor { |
assertEquals(5, future.get().intValue()); |
||||||
int submitStartCounter; |
assertEquals(1, obj.counter); |
||||||
int submitCompleteCounter; |
assertEquals(1, executor.submitStartCounter); |
||||||
|
assertEquals(1, executor.submitCompleteCounter); |
||||||
@Override |
} |
||||||
public <T> Future<T> submit(Callable<T> task) { |
|
||||||
submitStartCounter++; |
@Test |
||||||
Future<T> future = super.submit(task); |
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() { |
||||||
submitCompleteCounter++; |
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation(); |
||||||
synchronized (this) { |
int returnValue = obj.return5(); |
||||||
notifyAll(); |
assertEquals(5, returnValue); |
||||||
} |
assertEquals(0, executor.submitStartCounter); |
||||||
return future; |
assertEquals(0, executor.submitCompleteCounter); |
||||||
} |
} |
||||||
|
|
||||||
public synchronized void waitForCompletion() { |
@SuppressWarnings("serial") |
||||||
try { |
private static class CountingExecutor extends SimpleAsyncTaskExecutor { |
||||||
wait(WAIT_TIME); |
int submitStartCounter; |
||||||
} catch (InterruptedException e) { |
int submitCompleteCounter; |
||||||
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds"); |
|
||||||
} |
@Override |
||||||
} |
public <T> Future<T> submit(Callable<T> task) { |
||||||
} |
submitStartCounter++; |
||||||
|
Future<T> future = super.submit(task); |
||||||
static class ClassWithoutAsyncAnnotation { |
submitCompleteCounter++; |
||||||
int counter; |
synchronized (this) { |
||||||
|
notifyAll(); |
||||||
@Async public void incrementAsync() { |
} |
||||||
counter++; |
return future; |
||||||
} |
} |
||||||
|
|
||||||
public void increment() { |
public synchronized void waitForCompletion() { |
||||||
counter++; |
try { |
||||||
} |
wait(WAIT_TIME); |
||||||
|
} catch (InterruptedException e) { |
||||||
@Async public Future<Integer> incrementReturningAFuture() { |
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds"); |
||||||
counter++; |
} |
||||||
return new AsyncResult<Integer>(5); |
} |
||||||
} |
} |
||||||
|
|
||||||
// It should be an error to attach @Async to a method that returns a non-void
|
static class ClassWithoutAsyncAnnotation { |
||||||
// or non-Future.
|
int counter; |
||||||
// We need to keep this commented out, otherwise there will be a compile-time error.
|
|
||||||
// Please uncomment and re-comment this periodically to check that the compiler
|
@Async public void incrementAsync() { |
||||||
// produces an error message due to the 'declare error' statement
|
counter++; |
||||||
// in AnnotationDrivenAsynchronousExecutionAspect
|
} |
||||||
// @Async public int getInt() {
|
|
||||||
// return 0;
|
public void increment() { |
||||||
// }
|
counter++; |
||||||
} |
} |
||||||
|
|
||||||
@Async |
@Async public Future<Integer> incrementReturningAFuture() { |
||||||
static class ClassWithAsyncAnnotation { |
counter++; |
||||||
int counter; |
return new AsyncResult<Integer>(5); |
||||||
|
} |
||||||
public void increment() { |
|
||||||
counter++; |
// It should be an error to attach @Async to a method that returns a non-void
|
||||||
} |
// or non-Future.
|
||||||
|
// We need to keep this commented out, otherwise there will be a compile-time error.
|
||||||
// Manually check that there is a warning from the 'declare warning' statement in AnnotationDrivenAsynchronousExecutionAspect
|
// Please uncomment and re-comment this periodically to check that the compiler
|
||||||
public int return5() { |
// produces an error message due to the 'declare error' statement
|
||||||
return 5; |
// in AnnotationDrivenAsynchronousExecutionAspect
|
||||||
} |
// @Async public int getInt() {
|
||||||
|
// return 0;
|
||||||
public Future<Integer> incrementReturningAFuture() { |
// }
|
||||||
counter++; |
} |
||||||
return new AsyncResult<Integer>(5); |
|
||||||
} |
@Async |
||||||
} |
static class ClassWithAsyncAnnotation { |
||||||
} |
int counter; |
||||||
|
|
||||||
|
public void increment() { |
||||||
|
counter++; |
||||||
|
} |
||||||
|
|
||||||
|
// Manually check that there is a warning from the 'declare warning' statement in AnnotationDrivenAsynchronousExecutionAspect
|
||||||
|
public int return5() { |
||||||
|
return 5; |
||||||
|
} |
||||||
|
|
||||||
|
public Future<Integer> incrementReturningAFuture() { |
||||||
|
counter++; |
||||||
|
return new AsyncResult<Integer>(5); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue