/*
* Copyright 2016 requery.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.requery.test;
import io.requery.Persistable;
import io.requery.TransactionIsolation;
import io.requery.TransactionListener;
import io.requery.async.CompletableEntityStore;
import io.requery.async.CompletionStageEntityStore;
import io.requery.meta.EntityModel;
import io.requery.meta.Type;
import io.requery.sql.Configuration;
import io.requery.sql.ConfigurationBuilder;
import io.requery.sql.EntityDataStore;
import io.requery.sql.Platform;
import io.requery.sql.SchemaModifier;
import io.requery.sql.TableCreationMode;
import io.requery.sql.platform.HSQL;
import io.requery.test.model.Person;
import io.requery.test.model.Phone;
import io.requery.util.function.Supplier;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.sql.CommonDataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Function;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class CompletableEntityStoreTest extends RandomData {
protected CompletionStageEntityStore<Persistable> data;
private TransactionState transactionState;
private enum TransactionState {
BEGIN,
COMMIT,
ROLLBACK,
}
@Before
public void setup() throws SQLException {
Platform platform = new HSQL();
CommonDataSource dataSource = DatabaseType.getDataSource(platform);
EntityModel model = io.requery.test.model.Models.DEFAULT;
final TransactionListener transactionListener = new TransactionListener() {
@Override
public void beforeBegin(TransactionIsolation isolation) {
}
@Override
public void afterBegin(TransactionIsolation isolation) {
transactionState = TransactionState.BEGIN;
}
@Override
public void beforeCommit(Set<Type<?>> types) {
}
@Override
public void afterCommit(Set<Type<?>> types) {
transactionState = TransactionState.COMMIT;
}
@Override
public void beforeRollback(Set<Type<?>> types) {
}
@Override
public void afterRollback(Set<Type<?>> types) {
transactionState = TransactionState.ROLLBACK;
}
};
Configuration configuration = new ConfigurationBuilder(dataSource, model)
.useDefaultLogging()
.setStatementCacheSize(10)
.setBatchUpdateSize(50)
.setWriteExecutor(Executors.newSingleThreadExecutor())
.addTransactionListenerFactory(new Supplier<TransactionListener>() {
@Override
public TransactionListener get() {
return transactionListener;
}
})
.build();
data = new CompletableEntityStore<>(
new EntityDataStore<Persistable>(configuration));
SchemaModifier tables = new SchemaModifier(configuration);
tables.createTables(TableCreationMode.DROP_CREATE);
}
@After
public void teardown() {
if (data != null) {
data.close();
}
}
@Test
public void testInsert() throws Exception {
Person person = randomPerson();
data.insert(person).thenAccept(new Consumer<Person>() {
@Override
public void accept(Person person) {
assertTrue(person.getId() > 0);
Person cached = data.select(Person.class)
.where(Person.ID.equal(person.getId())).get().first();
assertSame(cached, person);
}
}).toCompletableFuture().get();
assertEquals(transactionState, TransactionState.COMMIT);
}
@Test
public void testInsertCount() throws Exception {
Person person = randomPerson();
data.insert(person).thenAccept(new Consumer<Person>() {
@Override
public void accept(Person person) {
assertTrue(person.getId() > 0);
}
}).thenCompose(new Function<Void, CompletionStage<Integer>>() {
@Override
public CompletionStage<Integer> apply(Void aVoid) {
return data.count(Person.class).get().toCompletableFuture();
}
}).toCompletableFuture().get();
}
@Test
public void testInsertOneToMany() throws Exception {
final Person person = randomPerson();
data.insert(person).thenApply(new Function<Person, Phone>() {
@Override
public Phone apply(Person person) {
Phone phone1 = randomPhone();
phone1.setOwner(person);
return phone1;
}
}).thenCompose(new Function<Phone, CompletionStage<Phone>>() {
@Override
public CompletionStage<Phone> apply(Phone phone) {
return data.insert(phone);
}
}).toCompletableFuture().get();
HashSet<Phone> set = new HashSet<>(person.getPhoneNumbers().toList());
assertEquals(1, set.size());
}
@Test
public void testQueryUpdate() throws ExecutionException, InterruptedException {
Person person = randomPerson();
person.setAge(100);
data.insert(person).toCompletableFuture().get();
CompletableFuture<Integer> rowCount = data.update(Person.class)
.set(Person.ABOUT, "nothing")
.set(Person.AGE, 50)
.where(Person.AGE.equal(100)).get()
.toCompletableFuture(Executors.newSingleThreadExecutor());
assertEquals(1, rowCount.get().intValue());
}
@Test
public void testInsertBlocking() throws Exception {
final Person person = randomPerson();
data.toBlocking().insert(person);
assertTrue(person.getId() > 0);
}
@Test
public void testQueryStream() throws Exception {
for (int i = 0; i < 30; i++) {
Person person = randomPerson();
data.insert(person).toCompletableFuture().get();
}
final List<Person> people = new ArrayList<>();
data.select(Person.class).orderBy(Person.NAME.asc().nullsLast()).limit(50).get()
.stream().forEach(new Consumer<Person>() {
@Override
public void accept(Person person) {
people.add(person);
}
});
assertSame(30, people.size());
}
}