package org.jooby.ebean; import static com.typesafe.config.ConfigValueFactory.fromAnyRef; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.isA; import java.util.Properties; import javax.sql.DataSource; import org.jooby.Env; import org.jooby.Env.ServiceKey; import org.jooby.internal.ebean.EbeanEnhancer; import org.jooby.internal.ebean.EbeanManaged; import org.jooby.test.MockUnit; import org.jooby.test.MockUnit.Block; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.common.collect.Sets; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.LinkedBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.google.inject.name.Names; import com.typesafe.config.Config; import com.typesafe.config.ConfigValueFactory; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.ebean.EbeanServer; import io.ebean.config.ContainerConfig; import io.ebean.config.ServerConfig; import javaslang.control.Try.CheckedRunnable; @RunWith(PowerMockRunner.class) @PrepareForTest({Ebeanby.class, ServerConfig.class, EbeanEnhancer.class, Properties.class }) public class EbeanbyTest { private Block containerConfig = unit -> { ContainerConfig config = unit.mockConstructor(ContainerConfig.class); config.loadFromProperties(isA(Properties.class)); unit.registerMock(ContainerConfig.class, config); }; @SuppressWarnings("unchecked") private Block binder = unit -> { Binder binder = unit.get(Binder.class); ScopedBindingBuilder sbbES = unit.mock(ScopedBindingBuilder.class); sbbES.asEagerSingleton(); sbbES.asEagerSingleton(); LinkedBindingBuilder<EbeanServer> lbbES = unit.mock(LinkedBindingBuilder.class); expect(lbbES.toProvider(isA(EbeanManaged.class))).andReturn(sbbES).times(2); expect(binder.bind(Key.get(EbeanServer.class))).andReturn(lbbES); expect(binder.bind(Key.get(EbeanServer.class, Names.named("db")))).andReturn(lbbES); }; private Block onStop = unit -> { Env env = unit.get(Env.class); expect(env.onStart(isA(CheckedRunnable.class))).andReturn(env); expect(env.onStop(isA(CheckedRunnable.class))).andReturn(env); expect(env.onStop(isA(CheckedRunnable.class))).andReturn(env); }; @Test public void configure() throws Exception { new MockUnit(Env.class, Binder.class) .expect(props("com.ibm.db2.jcc.DB2SimpleDataSource", "jdbc:db2://127.0.0.1/db", "db2.db", null, "", false)) .expect(hikariConfig()) .expect(hikariDataSource()) .expect(serviceKey("db")) .expect(containerConfig) .expect(serverConfig(true)) .expect(enhancer("my.model")) .expect(ebeanProperties()) .expect(binder) .expect(onStop) .run(unit -> { new Ebeanby("db") .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }); } @Test public void configureWithPackages() throws Exception { new MockUnit(Env.class, Binder.class) .expect(props("com.ibm.db2.jcc.DB2SimpleDataSource", "jdbc:db2://127.0.0.1/db", "db2.db", null, "", false)) .expect(hikariConfig()) .expect(hikariDataSource()) .expect(serviceKey("db")) .expect(ebeanProperties()) .expect(containerConfig) .expect(serverConfig(true)) .expect(enhancer("otro.package", "my.model")) .expect(binder) .expect(unit -> { ServerConfig conf = unit.get(ServerConfig.class); conf.addPackage("otro.package"); }) .expect(onStop) .run(unit -> { new Ebeanby() .packages("otro.package") .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }); } @Test public void configureCallback() throws Exception { new MockUnit(Env.class, Binder.class) .expect(props("com.ibm.db2.jcc.DB2SimpleDataSource", "jdbc:db2://127.0.0.1/db", "db2.db", null, "", false)) .expect(hikariConfig()) .expect(hikariDataSource()) .expect(serviceKey("db")) .expect(ebeanProperties()) .expect(containerConfig) .expect(serverConfig(true)) .expect(enhancer("my.model")) .expect(binder) .expect(unit -> { ServerConfig conf = unit.get(ServerConfig.class); conf.setName("xx"); }) .expect(onStop) .run(unit -> { new Ebeanby() .doWith((final ServerConfig conf) -> { conf.setName("xx"); }) .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }); } @Test public void configureCustomOption() throws Exception { new MockUnit(Env.class, Binder.class) .expect(props("com.ibm.db2.jcc.DB2SimpleDataSource", "jdbc:db2://127.0.0.1/db", "db2.db", null, "", false)) .expect(hikariConfig()) .expect(hikariDataSource()) .expect(serviceKey("db")) .expect(unit -> { Properties props = unit.constructor(Properties.class).build(); expect(props.setProperty("ebean.register", "true")).andReturn(null); expect(props.setProperty("ebean.defaultServer", "false")).andReturn(null); expect(props.setProperty("ebean.ddl.run", "false")).andReturn(null); expect(props.setProperty("ebean.logging.txnCommit", "none")).andReturn(null); expect(props.setProperty("ebean.logging.directory", "logs")).andReturn(null); expect(props.setProperty("ebean.logging.query", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.iud", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.sqlquery", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.logfilesharing", "all")).andReturn(null); expect(props.setProperty("ebean.loggingToJavaLogger", "false")).andReturn(null); expect(props.setProperty("ebean.ddl.generate", "false")).andReturn(null); expect(props.setProperty("ebean.debug.sql", "true")).andReturn(null); expect(props.setProperty("ebean.debug.lazyload", "false")).andReturn(null); expect(props.setProperty("ebean.disableClasspathSearch", "true")).andReturn(null); expect(props.setProperty("ebean.search.packages", "my.model")).andReturn(null); unit.registerMock(Properties.class, props); }) .expect(containerConfig) .expect(serverConfig(false)) .expect(enhancer("my.model")) .expect(binder) .expect(onStop) .run(unit -> { Config customConfig = config().withValue("ebean.db.defaultServer", ConfigValueFactory.fromAnyRef(false)); new Ebeanby("db") .configure(unit.get(Env.class), customConfig, unit.get(Binder.class)); }); } private Config config() { return new Ebeanby().config() .withValue("db", ConfigValueFactory.fromAnyRef("jdbc:db2://127.0.0.1/db")) .withValue("application.ns", ConfigValueFactory.fromAnyRef("my.model")) .withValue("application.tmpdir", ConfigValueFactory.fromAnyRef("target")) .withValue("application.name", ConfigValueFactory.fromAnyRef("model")) .withValue("application.charset", ConfigValueFactory.fromAnyRef("UTF-8")) .withValue("runtime.processors-x2", fromAnyRef("4")) .resolve(); } private Block enhancer(final String... packages) { return unit -> { EbeanEnhancer enhancer = unit.mock(EbeanEnhancer.class); enhancer.run(Sets.newHashSet(packages)); unit.mockStatic(EbeanEnhancer.class); expect(EbeanEnhancer.newEnhancer()).andReturn(enhancer); }; } private Block serverConfig(final boolean defaultServer) { return unit -> { ServerConfig serverConfig = unit.mockConstructor(ServerConfig.class); serverConfig.setName("db"); serverConfig.addPackage("my.model"); serverConfig.setContainerConfig(unit.get(ContainerConfig.class)); serverConfig.setDataSource(isA(DataSource.class)); serverConfig.loadFromProperties(isA(Properties.class)); serverConfig.setDefaultServer(defaultServer); serverConfig.setRegister(true); unit.registerMock(ServerConfig.class, serverConfig); }; } @SuppressWarnings("unchecked") private Block serviceKey(final String db) { return unit -> { ServiceKey skey = new Env.ServiceKey(); Env env = unit.get(Env.class); expect(env.serviceKey()).andReturn(skey).times(2); AnnotatedBindingBuilder<DataSource> binding = unit.mock(AnnotatedBindingBuilder.class); binding.toInstance(unit.get(HikariDataSource.class)); binding.toInstance(unit.get(HikariDataSource.class)); Binder binder = unit.get(Binder.class); expect(binder.bind(Key.get(DataSource.class))).andReturn(binding); expect(binder.bind(Key.get(DataSource.class, Names.named(db)))).andReturn(binding); }; } private Block hikariConfig() { return unit -> { Properties properties = unit.get(Properties.class); HikariConfig hikari = unit.constructor(HikariConfig.class) .build(properties); unit.registerMock(HikariConfig.class, hikari); }; } private Block hikariDataSource() { return unit -> { HikariConfig properties = unit.get(HikariConfig.class); HikariDataSource hikari = unit.constructor(HikariDataSource.class) .build(properties); unit.registerMock(HikariDataSource.class, hikari); }; } private Block props(final String dataSourceClassName, final String url, final String name, final String username, final String password, final boolean hasDataSourceClassName) { return unit -> { Properties properties = unit.constructor(Properties.class) .build(); expect(properties .setProperty("dataSource.dataSourceClassName", dataSourceClassName)) .andReturn(null); if (username != null) { expect(properties .setProperty("dataSource.user", username)) .andReturn(null); expect(properties .setProperty("dataSource.password", password)) .andReturn(null); } expect(properties .setProperty("dataSource.url", url)) .andReturn(null); if (hasDataSourceClassName) { expect(properties.getProperty("dataSourceClassName")).andReturn(dataSourceClassName); } else { expect(properties.getProperty("dataSourceClassName")).andReturn(null); expect(properties.getProperty("dataSource.dataSourceClassName")) .andReturn(dataSourceClassName); expect(properties.setProperty("dataSourceClassName", dataSourceClassName)).andReturn(null); } expect(properties.remove("dataSource.dataSourceClassName")).andReturn(dataSourceClassName); expect(properties.setProperty("poolName", name)).andReturn(null); expect(properties.setProperty("maximumPoolSize", "4")).andReturn(null); unit.registerMock(Properties.class, properties); }; } private Block ebeanProperties() { return unit -> { Properties props = unit.constructor(Properties.class).build(); expect(props.setProperty("ebean.register", "true")).andReturn(null); expect(props.setProperty("ebean.defaultServer", "true")).andReturn(null); expect(props.setProperty("ebean.ddl.run", "false")).andReturn(null); expect(props.setProperty("ebean.logging.txnCommit", "none")).andReturn(null); expect(props.setProperty("ebean.logging.directory", "logs")).andReturn(null); expect(props.setProperty("ebean.logging.query", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.iud", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.sqlquery", "sql")).andReturn(null); expect(props.setProperty("ebean.logging.logfilesharing", "all")).andReturn(null); expect(props.setProperty("ebean.loggingToJavaLogger", "false")).andReturn(null); expect(props.setProperty("ebean.ddl.generate", "false")).andReturn(null); expect(props.setProperty("ebean.debug.sql", "true")).andReturn(null); expect(props.setProperty("ebean.debug.lazyload", "false")).andReturn(null); expect(props.setProperty("ebean.disableClasspathSearch", "true")).andReturn(null); expect(props.setProperty("ebean.search.packages", "my.model")).andReturn(null); unit.registerMock(Properties.class, props); }; } }