package org.jooby.querydsl;
import static com.typesafe.config.ConfigValueFactory.fromAnyRef;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.junit.Assert.assertEquals;
import java.util.Properties;
import javax.sql.DataSource;
import org.jooby.Env;
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.inject.Binder;
import com.google.inject.Key;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.name.Names;
import com.querydsl.sql.CUBRIDTemplates;
import com.querydsl.sql.Configuration;
import com.querydsl.sql.DB2Templates;
import com.querydsl.sql.FirebirdTemplates;
import com.querydsl.sql.H2Templates;
import com.querydsl.sql.HSQLDBTemplates;
import com.querydsl.sql.MySQLTemplates;
import com.querydsl.sql.OracleTemplates;
import com.querydsl.sql.PostgreSQLTemplates;
import com.querydsl.sql.SQLCloseListener;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.SQLTemplates;
import com.querydsl.sql.SQLiteTemplates;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigValueFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javaslang.control.Try.CheckedRunnable;
@RunWith(PowerMockRunner.class)
@PrepareForTest({QueryDSL.class, Configuration.class, H2Templates.class })
public class QueryDSLTest {
private Block closeconf = unit -> {
Configuration conf = unit.get(Configuration.class);
conf.addListener(SQLCloseListener.DEFAULT);
};
private MockUnit.Block managed = unit -> {
Env env = unit.get(Env.class);
expect(env.onStop(isA(CheckedRunnable.class))).andReturn(env);
};
private Block newSQLQueryFactory = unit -> {
SQLQueryFactory factory = unit.constructor(SQLQueryFactory.class)
.build(unit.get(Configuration.class), unit.get(HikariDataSource.class));
unit.registerMock(SQLQueryFactory.class, factory);
};
@Test
public void defaults() throws Exception {
String url = "jdbc:h2:target/jdbctest";
new MockUnit(Env.class, Config.class, Binder.class)
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
"sa", "", false))
.expect(hikariConfig())
.expect(hikariDataSource(url))
.expect(serviceKey("jdbctest"))
.expect(sqlTemplate(H2Templates.class, null))
.expect(sqlTemplate(H2Templates.class, "jdbctest"))
.expect(conf(H2Templates.class))
.expect(bindconf(null))
.expect(bindconf("jdbctest"))
.expect(newSQLQueryFactory)
.expect(sqlqueryfactory(null))
.expect(sqlqueryfactory("jdbctest"))
.expect(managed)
.run(unit -> {
new QueryDSL()
.configure(unit.get(Env.class), config("fs"), unit.get(Binder.class));
});
}
@Test
public void dbProp() throws Exception {
String url = "jdbc:h2:target/jdbctest";
new MockUnit(Env.class, Config.class, Binder.class)
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
"sa", "", false))
.expect(hikariConfig())
.expect(hikariDataSource(url))
.expect(serviceKey("jdbctest"))
.expect(sqlTemplate(H2Templates.class, null))
.expect(sqlTemplate(H2Templates.class, "jdbctest"))
.expect(conf(H2Templates.class))
.expect(bindconf(null))
.expect(bindconf("jdbctest"))
.expect(newSQLQueryFactory)
.expect(sqlqueryfactory(null))
.expect(sqlqueryfactory("jdbctest"))
.expect(managed)
.run(unit -> {
new QueryDSL("db")
.configure(unit.get(Env.class), config("fs"), unit.get(Binder.class));
});
}
@Test
public void with() throws Exception {
String url = "jdbc:h2:target/jdbctest";
new MockUnit(Env.class, Config.class, Binder.class)
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
"sa", "", false))
.expect(hikariConfig())
.expect(hikariDataSource(url))
.expect(serviceKey("jdbctest"))
.expect(sqlTemplate(CUBRIDTemplates.class, null))
.expect(sqlTemplate(CUBRIDTemplates.class, "jdbctest"))
.expect(conf(CUBRIDTemplates.class))
.expect(newSQLQueryFactory)
.expect(bindconf(null))
.expect(bindconf("jdbctest"))
.expect(sqlqueryfactory(null))
.expect(sqlqueryfactory("jdbctest"))
.expect(managed)
.run(unit -> {
new QueryDSL()
.with(new CUBRIDTemplates())
.configure(unit.get(Env.class), config("fs"), unit.get(Binder.class));
});
}
@Test
public void doWith() throws Exception {
String url = "jdbc:h2:target/jdbctest";
new MockUnit(Env.class, Config.class, Binder.class)
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
"sa", "", false))
.expect(hikariConfig())
.expect(hikariDataSource(url))
.expect(serviceKey("jdbctest"))
.expect(sqlTemplate(H2Templates.class, null))
.expect(sqlTemplate(H2Templates.class, "jdbctest"))
.expect(conf(H2Templates.class))
.expect(newSQLQueryFactory)
.expect(closeconf)
.expect(bindconf(null))
.expect(bindconf("jdbctest"))
.expect(sqlqueryfactory(null))
.expect(sqlqueryfactory("jdbctest"))
.expect(managed)
.run(unit -> {
new QueryDSL()
.doWith((final Configuration conf) -> {
conf.addListener(SQLCloseListener.DEFAULT);
})
.configure(unit.get(Env.class), config("fs"), unit.get(Binder.class));
});
}
@Test
public void newSQLFactory() throws Exception {
String url = "jdbc:h2:target/jdbctest";
new MockUnit(Env.class, Config.class, Binder.class)
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
"sa", "", false))
.expect(hikariConfig())
.expect(hikariDataSource(url))
.expect(serviceKey("jdbctest"))
.expect(sqlTemplate(H2Templates.class, null))
.expect(sqlTemplate(H2Templates.class, "jdbctest"))
.expect(conf(H2Templates.class))
.expect(newSQLQueryFactory)
.expect(bindconf(null))
.expect(bindconf("jdbctest"))
.expect(sqlqueryfactory())
.expect(sqlqueryfactory(null))
.expect(sqlqueryfactory("jdbctest"))
.expect(managed)
.run(unit -> {
new QueryDSL()
.configure(unit.get(Env.class), config("fs"), unit.get(Binder.class));
});
}
@Test
public void db2() {
assertEquals(DB2Templates.class, QueryDSL.toSQLTemplates("db2").getClass());
}
@Test
public void mysql() {
assertEquals(MySQLTemplates.class, QueryDSL.toSQLTemplates("mysql").getClass());
}
@Test
public void mariadb() {
assertEquals(MySQLTemplates.class, QueryDSL.toSQLTemplates("mariadb").getClass());
}
@Test
public void h2() {
assertEquals(H2Templates.class, QueryDSL.toSQLTemplates("h2").getClass());
}
@Test
public void hsqldb() {
assertEquals(HSQLDBTemplates.class, QueryDSL.toSQLTemplates("hsqldb").getClass());
}
@Test
public void pgsql() {
assertEquals(PostgreSQLTemplates.class, QueryDSL.toSQLTemplates("pgsql").getClass());
}
@Test
public void postgresql() {
assertEquals(PostgreSQLTemplates.class, QueryDSL.toSQLTemplates("postgresql").getClass());
}
@Test
public void sqlite() {
assertEquals(SQLiteTemplates.class, QueryDSL.toSQLTemplates("sqlite").getClass());
}
@Test
public void oracle() {
assertEquals(OracleTemplates.class, QueryDSL.toSQLTemplates("oracle").getClass());
}
@Test
public void firebirdsql() {
assertEquals(FirebirdTemplates.class, QueryDSL.toSQLTemplates("firebirdsql").getClass());
}
@Test(expected = IllegalStateException.class)
public void shouldFailOnError() {
QueryDSL.toSQLTemplates("xxx");
}
private Block sqlqueryfactory() {
return unit -> {
unit.constructor(DataSource.class);
};
}
@SuppressWarnings({"unchecked", "rawtypes" })
private Block sqlqueryfactory(final String name) {
return unit -> {
LinkedBindingBuilder lbb = unit.mock(LinkedBindingBuilder.class);
lbb.toInstance(unit.get(SQLQueryFactory.class));
Binder binder = unit.get(Binder.class);
expect(binder.bind(key(SQLQueryFactory.class, name))).andReturn(lbb);
};
}
private <T extends SQLTemplates> Block conf(final Class<T> t) {
return unit -> {
Configuration conf = unit.constructor(Configuration.class)
.args(SQLTemplates.class)
.build(isA(t));
unit.registerMock(Configuration.class, conf);
};
}
@SuppressWarnings("unchecked")
private Block bindconf(final String name) {
return unit -> {
LinkedBindingBuilder<Configuration> lbb = unit.mock(LinkedBindingBuilder.class);
lbb.toInstance(unit.get(Configuration.class));
Binder binder = unit.get(Binder.class);
expect(binder.bind(key(Configuration.class, name))).andReturn(lbb);
};
}
@SuppressWarnings({"unchecked", "rawtypes" })
private <T extends SQLTemplates> Block sqlTemplate(final Class<T> template, final String name) {
return unit -> {
LinkedBindingBuilder lbb = unit.mock(LinkedBindingBuilder.class);
lbb.toInstance(isA(template));
Binder binder = unit.get(Binder.class);
expect(binder.bind(key(SQLTemplates.class, name))).andReturn(lbb);
};
}
private <T> Key<T> key(final Class<T> template, final String name) {
return name == null ? Key.get(template) : Key.get(template, Names.named(name));
}
public Config config(final String db) {
return new QueryDSL().config()
.withValue("db", ConfigValueFactory.fromAnyRef(db))
.withValue("application.ns", ConfigValueFactory.fromAnyRef("my.model"))
.withValue("application.tmpdir", ConfigValueFactory.fromAnyRef("target"))
.withValue("application.name", ConfigValueFactory.fromAnyRef("jdbctest"))
.withValue("application.charset", ConfigValueFactory.fromAnyRef("UTF-8"))
.withValue("runtime.processors-x2", fromAnyRef("4"))
.resolve();
}
@SuppressWarnings("unchecked")
private Block serviceKey(final String db) {
return unit -> {
Env env = unit.get(Env.class);
expect(env.serviceKey()).andReturn(new Env.ServiceKey()).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(final String url) {
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);
};
}
}