/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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 com.hazelcast.map.impl.query; import com.hazelcast.config.Config; import com.hazelcast.config.InMemoryFormat; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.IMap; import com.hazelcast.mock.MockUtil; import com.hazelcast.query.EntryObject; import com.hazelcast.query.Predicate; import com.hazelcast.query.PredicateBuilder; import com.hazelcast.query.SampleObjects.Employee; import com.hazelcast.spi.properties.GroupProperty; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.HazelcastTestSupport; import com.hazelcast.test.TestHazelcastInstanceFactory; import com.hazelcast.test.annotation.ParallelTest; import com.hazelcast.test.annotation.QuickTest; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.util.Collection; import java.util.HashMap; import java.util.Map; import static java.util.Collections.emptyList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @RunWith(HazelcastParallelClassRunner.class) @Category({QuickTest.class, ParallelTest.class}) public class QueryIndexingTest extends HazelcastTestSupport { private int count = 2000; private Map<Integer, Employee> employees; private TestHazelcastInstanceFactory nodeFactory; private HazelcastInstance h1; private HazelcastInstance h2; private Predicate predicate; @Before public void setUp() { employees = newEmployees(count); nodeFactory = createHazelcastInstanceFactory(2); Config config = newConfig(); h1 = nodeFactory.newHazelcastInstance(config); h2 = nodeFactory.newHazelcastInstance(config); EntryObject entryObject = new PredicateBuilder().getEntryObject(); predicate = entryObject.get("name").equal(null).and(entryObject.get("city").isNull()); assertClusterSizeEventually(2, h1); } @After public void tearDown() { nodeFactory.shutdownAll(); } @Test public void testResultsHaveNullFields_whenPredicateTestsForNull() { IMap<Integer, Employee> map = h1.getMap("employees"); map.putAll(employees); waitAllForSafeState(h1, h2); Collection<Employee> matchingEntries = runQueryNTimes(3, h2.<String, Employee>getMap("employees")); assertEquals(count / 2, matchingEntries.size()); // N queries result in getters called N times assertGettersCalledNTimes(matchingEntries, 3); assertFieldsAreNull(matchingEntries); } @Test public void testResultsHaveNullFields_whenUsingIndexes() { IMap<Integer, Employee> map = h1.getMap("employees"); map.addIndex("name", false); map.addIndex("city", true); map.putAll(employees); waitAllForSafeState(h1, h2); Collection<Employee> matchingEntries = runQueryNTimes(3, h2.<String, Employee>getMap("employees")); assertEquals(count / 2, matchingEntries.size()); assertFieldsAreNull(matchingEntries); } private static Map<Integer, Employee> newEmployees(int employeeCount) { Map<Integer, Employee> employees = new HashMap<Integer, Employee>(); for (int i = 0; i < employeeCount; i++) { Employee val; if (i % 2 == 0) { val = new Employee(i, null, null, 0, true, i); } else { val = new Employee(i, "name" + i, "city" + i, 0, true, i); } Employee spy = MockUtil.serializableSpy(Employee.class, val); employees.put(i, spy); } return employees; } private static Config newConfig() { Config conf = new Config(); conf.getMapConfig("employees").setInMemoryFormat(InMemoryFormat.OBJECT).setBackupCount(0); // disabling replication since we don't use backups in this test conf.setProperty(GroupProperty.PARTITION_MAX_PARALLEL_REPLICATIONS.getName(), "0"); return conf; } private Collection<Employee> runQueryNTimes(int queryCount, IMap<String, Employee> map) { Collection<Employee> result = emptyList(); for (int i = 0; i < queryCount; i++) { result = map.values(predicate); } return result; } private static void assertGettersCalledNTimes(Collection<Employee> matchingEmployees, int expectedCalls) { for (Employee employee : matchingEmployees) { verify(employee, times(expectedCalls)).getCity(); verify(employee, times(expectedCalls)).getName(); } } private static void assertFieldsAreNull(Collection<Employee> matchingEmployees) { for (Employee employee : matchingEmployees) { assertNull("city", employee.getCity()); assertNull("name", employee.getName()); } } }