package org.infinispan.client.hotrod.marshall;
import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager;
import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import org.infinispan.Cache;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.Search;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.client.hotrod.query.testdomain.protobuf.AccountPB;
import org.infinispan.client.hotrod.query.testdomain.protobuf.TransactionPB;
import org.infinispan.client.hotrod.query.testdomain.protobuf.UserPB;
import org.infinispan.client.hotrod.query.testdomain.protobuf.marshallers.GenderMarshaller;
import org.infinispan.client.hotrod.query.testdomain.protobuf.marshallers.MarshallerRegistration;
import org.infinispan.client.hotrod.query.testdomain.protobuf.marshallers.NotIndexedMarshaller;
import org.infinispan.client.hotrod.test.HotRodClientTestingUtil;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.commons.util.Util;
import org.infinispan.configuration.cache.Index;
import org.infinispan.filter.AbstractKeyValueFilterConverter;
import org.infinispan.filter.KeyValueFilterConverterFactory;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.metadata.Metadata;
import org.infinispan.protostream.FileDescriptorSource;
import org.infinispan.protostream.SerializationContext;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.SearchManager;
import org.infinispan.query.dsl.Query;
import org.infinispan.query.dsl.QueryFactory;
import org.infinispan.query.dsl.embedded.testdomain.Account;
import org.infinispan.query.dsl.embedded.testdomain.NotIndexed;
import org.infinispan.query.dsl.embedded.testdomain.Transaction;
import org.infinispan.query.dsl.embedded.testdomain.User;
import org.infinispan.query.dsl.embedded.testdomain.hsearch.AccountHS;
import org.infinispan.query.dsl.embedded.testdomain.hsearch.TransactionHS;
import org.infinispan.query.dsl.embedded.testdomain.hsearch.UserHS;
import org.infinispan.query.remote.CompatibilityProtoStreamMarshaller;
import org.infinispan.query.remote.ProtobufMetadataManager;
import org.infinispan.server.hotrod.HotRodServer;
import org.infinispan.test.SingleCacheManagerTest;
import org.infinispan.test.fwk.CleanupAfterMethod;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.testng.annotations.Test;
/**
* Tests compatibility between remote query and embedded mode.
*
* @author anistor@redhat.com
* @since 6.0
*/
@Test(testName = "client.hotrod.marshall.EmbeddedCompatTest", groups = "functional")
@CleanupAfterMethod
public class EmbeddedCompatTest extends SingleCacheManagerTest {
private static final String NOT_INDEXED_PROTO_SCHEMA = "package sample_bank_account;\n" +
"/* @Indexed(false) */\n" +
"message NotIndexed {\n" +
"\toptional string notIndexedField = 1;\n" +
"}\n";
private HotRodServer hotRodServer;
private RemoteCacheManager remoteCacheManager;
private RemoteCache<Integer, Account> remoteCache;
@Override
protected EmbeddedCacheManager createCacheManager() throws Exception {
org.infinispan.configuration.cache.ConfigurationBuilder builder = createConfigBuilder();
cacheManager = TestCacheManagerFactory.createCacheManager(builder);
cache = cacheManager.getCache();
hotRodServer = HotRodClientTestingUtil.startHotRodServer(cacheManager);
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort());
clientBuilder.marshaller(new ProtoStreamMarshaller());
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
remoteCache = remoteCacheManager.getCache();
//initialize client-side serialization context
SerializationContext clientSerCtx = ProtoStreamMarshaller.getSerializationContext(remoteCacheManager);
MarshallerRegistration.registerMarshallers(clientSerCtx);
clientSerCtx.registerProtoFiles(FileDescriptorSource.fromString("not_indexed.proto", NOT_INDEXED_PROTO_SCHEMA));
clientSerCtx.registerMarshaller(new NotIndexedMarshaller());
//initialize server-side serialization context
ProtobufMetadataManager protobufMetadataManager = cacheManager.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class);
protobufMetadataManager.registerProtofile("sample_bank_account/bank.proto", Util.read(Util.getResourceAsStream("/sample_bank_account/bank.proto", getClass().getClassLoader())));
protobufMetadataManager.registerProtofile("not_indexed.proto", NOT_INDEXED_PROTO_SCHEMA);
assertNull(protobufMetadataManager.getFileErrors("sample_bank_account/bank.proto"));
assertNull(protobufMetadataManager.getFileErrors("not_indexed.proto"));
assertNull(protobufMetadataManager.getFilesWithErrors());
protobufMetadataManager.registerMarshaller(new EmbeddedAccountMarshaller());
protobufMetadataManager.registerMarshaller(new EmbeddedUserMarshaller());
protobufMetadataManager.registerMarshaller(new GenderMarshaller());
protobufMetadataManager.registerMarshaller(new EmbeddedTransactionMarshaller());
protobufMetadataManager.registerMarshaller(new NotIndexedMarshaller());
return cacheManager;
}
protected org.infinispan.configuration.cache.ConfigurationBuilder createConfigBuilder() {
org.infinispan.configuration.cache.ConfigurationBuilder builder = hotRodCacheConfiguration();
builder.compatibility().enable().marshaller(new CompatibilityProtoStreamMarshaller());
builder.indexing().index(Index.ALL)
.addProperty("default.directory_provider", "ram")
.addProperty("lucene_version", "LUCENE_CURRENT");
return builder;
}
@Override
protected void teardown() {
killRemoteCacheManager(remoteCacheManager);
killServers(hotRodServer);
super.teardown();
}
public void testPutAndGet() throws Exception {
Account account = createAccountPB(1);
remoteCache.put(1, account);
// try to get the object through the local cache interface and check it's the same object we put
assertEquals(1, cache.keySet().size());
Object key = cache.keySet().iterator().next();
Object localObject = cache.get(key);
assertAccount((Account) localObject, AccountHS.class);
// get the object through the remote cache interface and check it's the same object we put
Account fromRemoteCache = remoteCache.get(1);
assertAccount(fromRemoteCache, AccountPB.class);
}
public void testPutAndGetForEmbeddedEntry() throws Exception {
AccountHS account = new AccountHS();
account.setId(1);
account.setDescription("test description");
account.setCreationDate(new Date(42));
cache.put(1, account);
// try to get the object through the local cache interface and check it's the same object we put
assertEquals(1, remoteCache.keySet().size());
Object key = remoteCache.keySet().iterator().next();
Object remoteObject = remoteCache.get(key);
assertAccount((Account) remoteObject, AccountPB.class);
// get the object through the embedded cache interface and check it's the same object we put
Account fromEmbeddedCache = (Account) cache.get(1);
assertAccount(fromEmbeddedCache, AccountHS.class);
}
public void testRemoteQuery() throws Exception {
Account account = createAccountPB(1);
remoteCache.put(1, account);
// get account back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(AccountPB.class)
.having("description").like("%test%")
.build();
List<Account> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertAccount(list.get(0), AccountPB.class);
}
public void testRemoteQueryForEmbeddedEntry() throws Exception {
AccountHS account = new AccountHS();
account.setId(1);
account.setDescription("test description");
account.setCreationDate(new Date(42));
cache.put(1, account);
// get account back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(AccountPB.class)
.having("description").like("%test%")
.build();
List<Account> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertAccount(list.get(0), AccountPB.class);
}
public void testRemoteQueryForEmbeddedEntryOnNonIndexedField() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
// get user back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(UserPB.class)
.having("notes").like("%567%")
.build();
List<User> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals(UserPB.class, list.get(0).getClass());
assertEquals(1, list.get(0).getId());
assertEquals("1234567890", list.get(0).getNotes());
}
public void testRemoteQueryForEmbeddedEntryOnNonIndexedType() throws Exception {
cache.put(1, new NotIndexed("testing 123"));
// get user back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from("sample_bank_account.NotIndexed")
.having("notIndexedField").like("%123%")
.build();
List<NotIndexed> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals("testing 123", list.get(0).notIndexedField);
}
public void testRemoteQueryForEmbeddedEntryOnIndexedAndNonIndexedField() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
// get user back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(UserPB.class)
.having("notes").like("%567%")
.and()
.having("surname").eq("test surname")
.build();
List<User> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals(UserPB.class, list.get(0).getClass());
assertEquals(1, list.get(0).getId());
assertEquals("1234567890", list.get(0).getNotes());
assertEquals("test surname", list.get(0).getSurname());
}
public void testRemoteQueryWithProjectionsForEmbeddedEntry() throws Exception {
AccountHS account = new AccountHS();
account.setId(1);
account.setDescription("test description");
account.setCreationDate(new Date(42));
cache.put(1, account);
// get account back from remote cache via query and check its attributes
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(AccountPB.class)
.select("description", "id")
.having("description").like("%test%")
.build();
List<Object[]> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertEquals("test description", list.get(0)[0]);
assertEquals(1, list.get(0)[1]);
}
public void testRemoteFullTextQuery() {
Transaction transaction = new TransactionHS();
transaction.setId(3);
transaction.setDescription("Hotel");
transaction.setLongDescription("Expenses for Infinispan F2F meeting");
transaction.setAccountId(2);
transaction.setAmount(99);
transaction.setDate(new Date(42));
transaction.setDebit(true);
transaction.setValid(true);
cache.put(transaction.getId(), transaction);
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query q = qf.create("from sample_bank_account.Transaction where longDescription:'f2f'");
List<Transaction> list = q.list();
assertEquals(1, list.size());
}
public void testEmbeddedLuceneQuery() throws Exception {
Account account = createAccountPB(1);
remoteCache.put(1, account);
// get account back from local cache via query and check its attributes
SearchManager searchManager = org.infinispan.query.Search.getSearchManager(cache);
org.apache.lucene.search.Query query = searchManager
.buildQueryBuilderForClass(AccountHS.class).get()
.keyword().wildcard().onField("description").matching("*test*").createQuery();
CacheQuery<Account> cacheQuery = searchManager.getQuery(query);
List<Account> list = cacheQuery.list();
assertNotNull(list);
assertEquals(1, list.size());
assertAccount(list.get(0), AccountHS.class);
}
public void testEmbeddedQueryForEmbeddedEntryOnNonIndexedField() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
// get user back from remote cache via query and check its attributes
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query query = qf.from(UserHS.class)
.having("notes").like("%567%")
.build();
List<User> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals(UserHS.class, list.get(0).getClass());
assertEquals(1, list.get(0).getId());
assertEquals("1234567890", list.get(0).getNotes());
}
public void testEmbeddedQueryForEmbeddedEntryOnNonIndexedType() throws Exception {
cache.put(1, new NotIndexed("testing 123"));
// get user back from remote cache via query and check its attributes
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query query = qf.from(NotIndexed.class)
.having("notIndexedField").like("%123%")
.build();
List<NotIndexed> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals("testing 123", list.get(0).notIndexedField);
}
public void testEmbeddedQueryForEmbeddedEntryOnIndexedAndNonIndexedField() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
// get user back from remote cache via query and check its attributes
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query query = qf.from(UserHS.class)
.having("notes").like("%567%")
.and()
.having("surname").eq("test surname")
.build();
List<User> list = query.list();
assertNotNull(list);
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertEquals(UserHS.class, list.get(0).getClass());
assertEquals(1, list.get(0).getId());
assertEquals("1234567890", list.get(0).getNotes());
assertEquals("test surname", list.get(0).getSurname());
}
public void testIterationForRemote() throws Exception {
IntStream.range(0, 10).forEach(id -> remoteCache.put(id, createAccountPB(id)));
// Remote unfiltered iteration
CloseableIterator<Map.Entry<Object, Object>> remoteUnfilteredIterator = remoteCache.retrieveEntries(null, null, 10);
remoteUnfilteredIterator.forEachRemaining(e -> {
Integer key = (Integer) e.getKey();
AccountPB value = (AccountPB) e.getValue();
assertTrue(key < 10);
assertTrue(value.getId() == key);
});
// Remote filtered iteration
KeyValueFilterConverterFactory<Integer, Account, String> filterConverterFactory = () ->
new AbstractKeyValueFilterConverter<Integer, Account, String>() {
@Override
public String filterAndConvert(Integer key, Account value, Metadata metadata) {
if (key % 2 == 0) {
return value.toString();
}
return null;
}
};
hotRodServer.addKeyValueFilterConverterFactory("filterConverterFactory", filterConverterFactory);
CloseableIterator<Map.Entry<Object, Object>> remoteFilteredIterator = remoteCache.retrieveEntries("filterConverterFactory", null, 10);
remoteFilteredIterator.forEachRemaining(e -> {
Integer key = (Integer) e.getKey();
String value = (String) e.getValue();
assertTrue(key < 10);
assertTrue(value.equals(createAccountHS(key).toString()));
});
// Embedded iteration
Cache<Integer, AccountHS> ourCache = cache();
Iterator<Map.Entry<Integer, AccountHS>> localUnfilteredIterator = ourCache.entrySet().stream().iterator();
localUnfilteredIterator.forEachRemaining(e -> {
Integer key = e.getKey();
AccountHS value = e.getValue();
assertTrue(key < 10);
assertTrue(value.getId() == key);
});
}
public void testEqEmptyStringRemote() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query q = qf.from(UserPB.class)
.having("name").eq("")
.build();
List<User> list = q.list();
assertTrue(list.isEmpty());
}
public void testEqSentenceRemote() throws Exception {
AccountHS account = new AccountHS();
account.setId(1);
account.setDescription("John Doe's first bank account");
account.setCreationDate(new Date(42));
cache.put(1, account);
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query q = qf.from(AccountPB.class)
.having("description").eq("John Doe's first bank account")
.build();
List<Account> list = q.list();
assertEquals(1, list.size());
assertEquals(1, list.get(0).getId());
}
public void testEqEmptyStringEmbedded() throws Exception {
UserHS user = new UserHS();
user.setId(1);
user.setName("test name");
user.setSurname("test surname");
user.setGender(User.Gender.MALE);
user.setNotes("1234567890");
cache.put(1, user);
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query q = qf.from(UserHS.class)
.having("name").eq("")
.build();
List<User> list = q.list();
assertTrue(list.isEmpty());
}
public void testEqSentenceEmbedded() throws Exception {
AccountHS account = new AccountHS();
account.setId(1);
account.setDescription("John Doe's first bank account");
account.setCreationDate(new Date(42));
cache.put(1, account);
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query q = qf.from(AccountHS.class)
.having("description").eq("John Doe's first bank account")
.build();
List<Account> list = q.list();
assertEquals(1, list.size());
assertEquals(1, list.get(0).getId());
}
public void testDuplicateBooleanProjectionEmbedded() {
Transaction transaction = new TransactionHS();
transaction.setId(3);
transaction.setDescription("Hotel");
transaction.setAccountId(2);
transaction.setAmount(45);
transaction.setDate(new Date(42));
transaction.setDebit(true);
transaction.setValid(true);
cache.put(transaction.getId(), transaction);
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query q = qf.from(TransactionHS.class)
.select("id", "isDebit", "isDebit")
.having("description").eq("Hotel")
.build();
List<Object[]> list = q.list();
assertEquals(1, list.size());
assertEquals(3, list.get(0).length);
assertEquals(3, list.get(0)[0]);
assertEquals(true, list.get(0)[1]);
assertEquals(true, list.get(0)[2]);
}
public void testDuplicateBooleanProjectionRemote() {
Transaction transaction = new TransactionHS();
transaction.setId(3);
transaction.setDescription("Hotel");
transaction.setAccountId(2);
transaction.setAmount(45);
transaction.setDate(new Date(42));
transaction.setDebit(true);
transaction.setValid(true);
cache.put(transaction.getId(), transaction);
QueryFactory qf = Search.getQueryFactory(remoteCache);
Query q = qf.from(TransactionPB.class)
.select("id", "isDebit", "isDebit")
.having("description").eq("Hotel")
.build();
List<Object[]> list = q.list();
assertEquals(1, list.size());
assertEquals(3, list.get(0).length);
assertEquals(3, list.get(0)[0]);
assertEquals(true, list.get(0)[1]);
assertEquals(true, list.get(0)[2]);
}
private AccountPB createAccountPB(int id) {
AccountPB account = new AccountPB();
account.setId(id);
account.setDescription("test description");
account.setCreationDate(new Date(42));
return account;
}
private AccountHS createAccountHS(int id) {
AccountHS account = new AccountHS();
account.setId(id);
account.setDescription("test description");
account.setCreationDate(new Date(42));
return account;
}
private void assertAccount(Account account, Class<?> cls) {
assertNotNull(account);
assertEquals(cls, account.getClass());
assertEquals(1, account.getId());
assertEquals("test description", account.getDescription());
assertEquals(42, account.getCreationDate().getTime());
}
}