package com.softwaremill.common.util.dependency;
import org.testng.annotations.Test;
import java.util.concurrent.Callable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.*;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class DTest {
public static class LoginInfo {
private final String login;
LoginInfo(String login) {
this.login = login;
}
public String getLogin() {
return login;
}
}
@Test
public void testAnotherThreadSetsDependency() throws InterruptedException {
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
D.withDependencies(new LoginInfo("user1"), new Callable<Void>() {
@Override
public Void call() throws Exception {
Thread.sleep(1000);
return null;
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
// Running r1 - the thread will sleep
Thread thread1 = new Thread(r1);
thread1.start();
Thread.sleep(200);
// The dependency shouldn't be available
assertCannotInjectLoginInfo();
// Cleanup
thread1.join();
}
@Test
public void testMultithreadedWithDependencies() throws InterruptedException {
final boolean[] r1ok = {true};
final boolean[] r2ok = {true};
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
D.withDependencies(new LoginInfo("user1"), new Callable<Void>() {
@Override
public Void call() throws Exception {
checkUser();
Thread.sleep(500);
checkUser();
return null;
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void checkUser() {
r1ok[0] = D.inject(LoginInfo.class).getLogin().equals("user1");
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
try {
D.withDependencies(new LoginInfo("user2"), new Callable<Void>() {
@Override
public Void call() throws Exception {
checkUser();
Thread.sleep(500);
checkUser();
return null;
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void checkUser() {
r2ok[0] = D.inject(LoginInfo.class).getLogin().equals("user2");
}
};
// First running r1
Thread thread1 = new Thread(r1);
thread1.start();
Thread.sleep(200);
// Now running r2
Thread thread2 = new Thread(r2);
thread2.start();
// The interleaving is:
// 0 - starting r1, checking, sleeping for 500
// 200 - starting r2, checking, sleeping for 500
// 500 - checking, stopping r1
// 700 - checking, stopping r2
// Waiting for the threads to finish
thread1.join();
thread2.join();
// Checking that they are both ok
assertThat(r1ok[0]).isTrue();
assertThat(r2ok[0]).isTrue();
assertCannotInjectLoginInfo();
}
@Test
public void testWithQualifiers() throws Exception {
LoginInfo info = new LoginInfo("user");
LoginInfo injected = D.withDependencies(D.qualifiedDependency(info, D.qualifier(TestQualifier.class)),
new Callable<LoginInfo>() {
@Override
public LoginInfo call() throws Exception {
return D.inject(LoginInfo.class, D.qualifier(TestQualifier.class));
}
});
assertThat(injected).isEqualTo(info);
}
@Test
public void testWithQualifiersFromClass() throws Exception {
LoginInfo info = new LoginInfo("user");
LoginInfo injected = D.withDependencies(D.qualifiedDependency(info, D.qualifier(TestQualifier.class)),
new Callable<LoginInfo>() {
@Override
public LoginInfo call() throws Exception {
return D.inject(LoginInfo.class, FooAnnotatedClass.class.getAnnotation(TestQualifier.class));
}
});
assertThat(injected).isEqualTo(info);
}
@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "No dependencies.+")
public void testWithNoAvailableQualifiers() throws Exception {
LoginInfo info = new LoginInfo("user");
LoginInfo injected = D.withDependencies(info,
new Callable<LoginInfo>() {
@Override
public LoginInfo call() throws Exception {
return D.inject(LoginInfo.class, D.qualifier(TestQualifier.class));
}
});
}
@Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = "No dependencies.+")
public void testWithNoWrongQualifiers() throws Exception {
LoginInfo info = new LoginInfo("user");
LoginInfo injected = D.withDependencies(D.qualifiedDependency(info, D.qualifier(TestQualifier.class)),
new Callable<LoginInfo>() {
@Override
public LoginInfo call() throws Exception {
return D.inject(LoginInfo.class, D.qualifier(AnotherTestQualifier.class));
}
});
System.out.println(injected);
}
private void assertCannotInjectLoginInfo() {
try {
D.inject(LoginInfo.class);
fail("Injected a login info!");
} catch (RuntimeException e) {
assertThat(e.getMessage().contains("No dependencies"));
}
}
}