Skip to content

Commit

Permalink
Refactored app creation, allow annotation to specify a factory
Browse files Browse the repository at this point in the history
  • Loading branch information
bbarkley committed Oct 19, 2015
1 parent ec89d08 commit 015723f
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 110 deletions.
10 changes: 9 additions & 1 deletion helpers/src/main/java/com/linkedin/plugin/NGTestsBase.java
Expand Up @@ -118,9 +118,16 @@ protected List<String> getPlugins(){
}

protected boolean isDefined(Class clz) {
return !Object.class.equals(clz);
return clz != null && !Object.class.equals(clz);
}

protected <T> T instantiate(Class<?> clazz) {
try {
return (T) clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("Unable to instantiate class " + clazz);
}
}

private Stream<Binding<?>> toStream(WithOverrides overrides) {
return Optional.ofNullable(overrides).map(o -> Arrays.stream(o.value()).map(this::toBinding)).orElse(Stream.empty());
Expand Down Expand Up @@ -168,5 +175,6 @@ private Class testClass() {
return itr.getTestClass().getRealClass();
}


}
}
@@ -0,0 +1,12 @@
package com.linkedin.plugin.j;

import play.Application;

/**
* Knows how to build applications using the data that is available from annotations.
*/
public interface FakeApplicationFactory {

Application buildApplication(FakeApplicationFactoryArgs args);

}
@@ -0,0 +1,57 @@
package com.linkedin.plugin.j;

import play.GlobalSettings;
import play.api.inject.Binding;
import play.inject.guice.GuiceBuilder;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class FakeApplicationFactoryArgs {
private final File _path;
private final Optional<Class<? extends GuiceBuilder>> _builderClass;
private final Optional<GlobalSettings> _global;
private final List<Binding<?>> _overrides;
private final Map<String, Object> _config;
private final List<String> _plugins;

public FakeApplicationFactoryArgs(File path,
Optional<Class<? extends GuiceBuilder>> builderClass,
Optional<GlobalSettings> global,
List<Binding<?>> overrides,
Map<String, Object> config,
List<String> plugins) {
_path = path;
_builderClass = builderClass;
_global = global;
_overrides = overrides;
_config = config;
_plugins = plugins;
}

public File getPath() {
return _path;
}

public Optional<Class<? extends GuiceBuilder>> getBuilderClass() {
return _builderClass;
}

public Optional<GlobalSettings> getGlobal() {
return _global;
}

public List<Binding<?>> getOverrides() {
return _overrides;
}

public Map<String, Object> getConfig() {
return _config;
}

public List<String> getPlugins() {
return _plugins;
}
}
@@ -0,0 +1,58 @@
package com.linkedin.plugin.j;

import play.Application;
import play.Environment;
import play.GlobalSettings;
import play.Mode;
import play.api.inject.Binding;
import play.api.inject.package$;
import play.inject.guice.GuiceApplicationBuilder;
import play.inject.guice.GuiceBuilder;
import play.test.FakeApplication;
import play.test.Helpers;

/**
* Default implementation for building an Application. If a builder isn't specified and no overrides are present the Play
* FakeApplication is used. Otherwise a builder is used. Using @WithPlugins and a builder or overrides isn't supported.
*/
public class FakeApplicationFactoryImpl implements FakeApplicationFactory {
@Override
public Application buildApplication(FakeApplicationFactoryArgs args) {
return shouldUseBuilder(args) ? buildFromBuilder(args) : buildFromFakeApp(args);
}

protected boolean shouldUseBuilder(FakeApplicationFactoryArgs args) {
return args.getBuilderClass().isPresent() || !args.getOverrides().isEmpty();
}

protected Application buildFromFakeApp(FakeApplicationFactoryArgs args) {
return new FakeApplication(args.getPath(), Helpers.class.getClassLoader(), args.getConfig(), args.getPlugins(), args.getGlobal().orElse(null));
}

protected Application buildFromBuilder(FakeApplicationFactoryArgs args) {
Class<? extends GuiceBuilder> builderClass = args.getBuilderClass().orElse(GuiceApplicationBuilder.class);
GuiceBuilder builder;
try {
builder = builderClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("Unable to instantiate application builder " + builderClass, e);
}
if (!args.getPlugins().isEmpty()) {
throw new RuntimeException("Using plugins isn't supported when using binding overrides or a GuiceBuilder.");
}

builder = (GuiceBuilder) builder.in(new Environment(args.getPath(), Helpers.class.getClassLoader(), Mode.TEST));
builder = (GuiceBuilder) builder.configure(args.getConfig());
if (args.getGlobal().isPresent()) {
GlobalSettings global = args.getGlobal().get();
if (builder instanceof GuiceApplicationBuilder) {
builder = ((GuiceApplicationBuilder) builder).global(global);
} else {
play.api.GlobalSettings scalaGlobal = new play.core.j.JavaGlobalSettingsAdapter(global);
builder = (GuiceBuilder) builder.bindings(package$.MODULE$.bind(play.api.GlobalSettings.class).toInstance(scalaGlobal));
}
}
builder = (GuiceBuilder) builder.overrides(args.getOverrides().toArray(new Binding[args.getOverrides().size()]));
return builder.injector().instanceOf(Application.class);
}
}
60 changes: 11 additions & 49 deletions helpers/src/main/java/com/linkedin/plugin/j/NGTests.java
Expand Up @@ -18,20 +18,14 @@
import org.testng.IHookable;
import org.testng.ITestResult;
import play.Application;
import play.Environment;
import play.GlobalSettings;
import play.Mode;
import play.api.inject.Binding;
import play.api.inject.package$;
import play.inject.guice.GuiceApplicationBuilder;
import play.inject.guice.GuiceBuilder;
import play.test.FakeApplication;
import play.test.Helpers;
import play.test.TestBrowser;
import play.test.TestServer;

import java.io.File;
import java.util.List;
import java.util.Optional;

import static play.test.Helpers.HTMLUNIT;

Expand All @@ -50,51 +44,19 @@ private Application buildFakeApplication(WithFakeApplication fa) {
if (fa == null) {
return null;
}
String path = fa.path();
GlobalSettings globalSettings = null;
if (isDefined(fa.withGlobal())) {
try {
globalSettings = (GlobalSettings) fa.withGlobal().newInstance();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
List<Binding<?>> overrides = getOverrides();
if (isDefined(fa.guiceBuilder()) || !overrides.isEmpty()) {
Class builderClass = Object.class.equals(fa.guiceBuilder()) ? GuiceApplicationBuilder.class : fa.guiceBuilder();
return buildFromBuilder(new File(path), globalSettings, builderClass, overrides);
}

return new FakeApplication(new File(path), Helpers.class.getClassLoader(), getConf(), getPlugins(), globalSettings);
FakeApplicationFactory appFactory = instantiate(fa.appFactory());

return appFactory.buildApplication(new FakeApplicationFactoryArgs(
new File(fa.path()),
isDefined(fa.guiceBuilder()) ? Optional.of(fa.guiceBuilder()) : Optional.<Class<? extends GuiceBuilder>>empty(),
isDefined(fa.withGlobal()) ? Optional.of(instantiate(fa.withGlobal())) : Optional.<GlobalSettings>empty(),
getOverrides(),
getConf(),
getPlugins()
));
}

/**
* Build from a 2.4 Builder instead of using FakeApplication
*/
private Application buildFromBuilder(File path, GlobalSettings globalSettings, Class<?> builderClass, List<Binding<?>> overrides) {
GuiceBuilder builder;
try {
builder = (GuiceBuilder) builderClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("Unable to instantiate application builder " + builderClass, e);
}
if (!getPlugins().isEmpty()) {
throw new RuntimeException("Using plugins isn't supported when using binding overrides or a GuiceBuilder.");
}

builder = (GuiceBuilder) builder.in(new Environment(path, Helpers.class.getClassLoader(), Mode.TEST));
builder = (GuiceBuilder) builder.configure(getConf());
if (globalSettings != null) {
if (builder instanceof GuiceApplicationBuilder) {
builder = ((GuiceApplicationBuilder) builder).global(globalSettings);
} else {
play.api.GlobalSettings scalaGlobal = new play.core.j.JavaGlobalSettingsAdapter(globalSettings);
builder = (GuiceBuilder) builder.bindings(package$.MODULE$.bind(play.api.GlobalSettings.class).toInstance(scalaGlobal));
}
}
builder = (GuiceBuilder) builder.overrides(overrides.toArray(new Binding[overrides.size()]));
return builder.injector().instanceOf(Application.class);
}

private TestServer buildTestServer(WithTestServer ts) {
Application fake = buildFakeApplication(ts.fakeApplication());
Expand Down
Expand Up @@ -24,4 +24,5 @@
String path() default ".";
Class withGlobal() default Object.class;
Class guiceBuilder() default Object.class;
Class<? extends FakeApplicationFactory> appFactory() default FakeApplicationFactoryImpl.class;
}
@@ -0,0 +1,10 @@
package com.linkedin.plugin.s;

import play.api.Application;

/**
* Knows how to build applications using the data that is available from annotations.
*/
public interface FakeApplicationFactory {
Application buildScalaApplication(FakeApplicationFactoryArgs args);
}
@@ -0,0 +1,57 @@
package com.linkedin.plugin.s;

import play.api.GlobalSettings;
import play.api.inject.Binding;
import play.api.inject.guice.GuiceBuilder;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class FakeApplicationFactoryArgs {
private final File _path;
private final Optional<Class<? extends GuiceBuilder>> _builderClass;
private final Optional<GlobalSettings> _global;
private final List<Binding<?>> _overrides;
private final Map<String, Object> _config;
private final List<String> _plugins;

public FakeApplicationFactoryArgs(File path,
Optional<Class<? extends GuiceBuilder>> builderClass,
Optional<GlobalSettings> global,
List<Binding<?>> overrides,
Map<String, Object> config,
List<String> plugins) {
_path = path;
_builderClass = builderClass;
_global = global;
_overrides = overrides;
_config = config;
_plugins = plugins;
}

public File getPath() {
return _path;
}

public Optional<Class<? extends GuiceBuilder>> getBuilderClass() {
return _builderClass;
}

public Optional<GlobalSettings> getGlobal() {
return _global;
}

public List<Binding<?>> getOverrides() {
return _overrides;
}

public Map<String, Object> getConfig() {
return _config;
}

public List<String> getPlugins() {
return _plugins;
}
}
@@ -0,0 +1,70 @@
package com.linkedin.plugin.s;

import play.api.Application;
import play.api.Environment;
import play.api.GlobalSettings;
import play.api.Mode;
import play.api.inject.guice.GuiceApplicationBuilder;
import play.api.inject.guice.GuiceBuilder;
import play.api.inject.package$;
import play.api.mvc.Handler;
import play.api.test.FakeApplication;
import play.api.test.Helpers;
import play.libs.Scala;
import scala.PartialFunction$;
import scala.Tuple2;

import java.util.Collections;

/**
* Default implementation for building an Application. If a builder isn't specified and no overrides are present the Play
* FakeApplication is used. Otherwise a builder is used. Using @WithPlugins and a builder or overrides isn't supported.
*/
public class FakeApplicationFactoryImpl implements FakeApplicationFactory {
@Override
public Application buildScalaApplication(FakeApplicationFactoryArgs args) {
return shouldUseBuilder(args) ? buildFromBuilder(args) : buildFromFakeApp(args);
}

protected boolean shouldUseBuilder(FakeApplicationFactoryArgs args) {
return args.getBuilderClass().isPresent() || !args.getOverrides().isEmpty();
}

protected Application buildFromBuilder(FakeApplicationFactoryArgs args) {
Class<? extends GuiceBuilder> builderClass = args.getBuilderClass().orElse(GuiceApplicationBuilder.class);
GuiceBuilder builder;
try {
builder = builderClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("Unable to instantiate application builder " + builderClass, e);
}
if (!args.getPlugins().isEmpty()) {
throw new RuntimeException("Using plugins isn't supported when using binding overrides or a GuiceBuilder.");
}
builder = (GuiceBuilder) builder.in(new Environment(args.getPath(), play.test.Helpers.class.getClassLoader(), Mode.Test()));
builder = (GuiceBuilder) builder.configure(Scala.asScala(args.getConfig()));
if (args.getGlobal().isPresent()) {
GlobalSettings global = args.getGlobal().get();
if (builder instanceof GuiceApplicationBuilder) {
builder = ((GuiceApplicationBuilder) builder).global(global);
} else {
builder = (GuiceBuilder) builder.bindings(Scala.varargs(package$.MODULE$.bind(play.api.GlobalSettings.class).toInstance(global)));
}
}
builder = (GuiceBuilder) builder.overrides(Scala.asScala(args.getOverrides()));
return builder.injector().instanceOf(Application.class);
}

protected Application buildFromFakeApp(FakeApplicationFactoryArgs args) {
return new FakeApplication(
args.getPath(),
Helpers.class.getClassLoader(),
Scala.toSeq(args.getPlugins()),
Scala.toSeq(Collections.<String>emptyList()),
Scala.asScala(args.getConfig()),
scala.Option.apply(args.getGlobal().orElse(null)),
PartialFunction$.MODULE$.<Tuple2<String, String>, Handler>empty()
);

}
}

0 comments on commit 015723f

Please sign in to comment.