/*
* 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.spi;
import com.hazelcast.internal.serialization.InternalSerializationService;
import com.hazelcast.internal.serialization.impl.DefaultSerializationServiceBuilder;
import com.hazelcast.nio.BufferObjectDataInput;
import com.hazelcast.nio.BufferObjectDataOutput;
import com.hazelcast.test.HazelcastSerialClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.lang.reflect.Constructor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@RunWith(HazelcastSerialClassRunner.class)
@Category(QuickTest.class)
public class OperationSerializationTest extends HazelcastTestSupport {
private static final String DUMMY_SERVICE_NAME = "foobar";
private InternalSerializationService serializationService;
@Before
public void setup() {
serializationService = new DefaultSerializationServiceBuilder().build();
}
@Test
public void test_partitionId() throws IOException {
test_partitionId(0, false);
test_partitionId(100, false);
test_partitionId(-1, false);
test_partitionId(Short.MAX_VALUE, false);
test_partitionId(Short.MAX_VALUE + 1, true);
test_partitionId(Integer.MAX_VALUE, true);
}
private void test_partitionId(int partitionId, boolean is32bit) {
Operation op = new DummyOperation();
op.setPartitionId(partitionId);
assertEquals(partitionId, op.getPartitionId());
assertEquals("is partition 32 bits", is32bit, op.isFlagSet(Operation.BITMASK_PARTITION_ID_32_BIT));
assertSerializationCloneEquals(op);
}
@Test
public void test_replicaIndex() throws IOException {
test_replicaIndex(0, false);
test_replicaIndex(1, true);
test_replicaIndex(3, true);
}
private void test_replicaIndex(int replicaIndex, boolean isReplicaIndexSet) {
Operation op = new DummyOperation();
op.setReplicaIndex(replicaIndex);
assertEquals(replicaIndex, op.getReplicaIndex());
assertEquals("is replicaindex set", isReplicaIndexSet, op.isFlagSet(Operation.BITMASK_REPLICA_INDEX_SET));
assertSerializationCloneEquals(op);
}
@Test
public void test_callTimeout() throws IOException {
test_callTimeout(0, false);
test_callTimeout(100, false);
test_callTimeout(-1, false);
test_callTimeout(Integer.MAX_VALUE, false);
test_callTimeout(Integer.MAX_VALUE + 1L, true);
test_callTimeout(Long.MAX_VALUE, true);
}
private void test_callTimeout(long callTimeout, boolean callTimeout64Bits) {
Operation op = new DummyOperation();
op.setCallTimeout(callTimeout);
assertEquals(callTimeout, op.getCallTimeout());
assertEquals("is calltimeout 64 bits", callTimeout64Bits, op.isFlagSet(Operation.BITMASK_CALL_TIMEOUT_64_BIT));
assertSerializationCloneEquals(op);
}
@Test
public void test_callId() {
Operation op = new DummyOperation();
op.setCallId(10000);
assertEquals(10000, op.getCallId());
assertSerializationCloneEquals(op);
}
@Test
public void test_invocationTime() {
Operation op = new DummyOperation();
op.setInvocationTime(10000);
assertEquals(10000, op.getInvocationTime());
assertSerializationCloneEquals(op);
}
@Test
public void test_waitTimeout() {
test_waitTimeout(-1, false);
test_waitTimeout(0, true);
test_waitTimeout(1, true);
}
private void test_waitTimeout(long waitTimeout, boolean waitTimeoutSet) {
Operation op = new DummyOperation();
op.setWaitTimeout(waitTimeout);
assertEquals(waitTimeout, op.getWaitTimeout());
assertEquals("wait timeout set", waitTimeoutSet, op.isFlagSet(Operation.BITMASK_WAIT_TIMEOUT_SET));
assertSerializationCloneEquals(op);
}
@Test
public void test_callerUuid() {
test_callerUuid(null, false);
test_callerUuid("", true);
test_callerUuid("foofbar", true);
}
private void test_callerUuid(String callerUuid, boolean callerUuidSet) {
Operation op = new DummyOperation();
op.setCallerUuid(callerUuid);
assertEquals(callerUuid, op.getCallerUuid());
assertEquals("wait timeout set", callerUuidSet, op.isFlagSet(Operation.BITMASK_CALLER_UUID_SET));
assertSerializationCloneEquals(op);
}
@Test
public void test_validateTarget_defaultValue() {
Operation op = new DummyOperation();
assertTrue("Default value of validate target should be TRUE", op.validatesTarget());
assertSerializationCloneEquals(op);
}
private void assertSerializationCloneEquals(Operation expected) {
Operation actual = copy(expected);
assertEquals("caller uuid does not match", expected.getCallerUuid(), actual.getCallerUuid());
assertEquals("call timeout does not match", expected.getCallTimeout(), actual.getCallTimeout());
assertEquals("validates target does not match", expected.validatesTarget(), actual.validatesTarget());
assertEquals("callid does not match", expected.getCallId(), actual.getCallId());
assertEquals("invocation time does not match", expected.getInvocationTime(), actual.getInvocationTime());
assertEquals("partitionId does not match", expected.getPartitionId(), actual.getPartitionId());
assertEquals("replica index does not match", expected.getReplicaIndex(), actual.getReplicaIndex());
assertEquals("state does not match", expected.getFlags(), actual.getFlags());
assertEquals("wait timeout does not match", expected.getWaitTimeout(), actual.getWaitTimeout());
}
@Test
public void test_serviceName_whenOverridesGetServiceName_thenNotSerialized() {
OperationWithServiceNameOverride op = new OperationWithServiceNameOverride();
assertNull(op.getRawServiceName());
assertFalse("service name should not be set", op.isFlagSet(Operation.BITMASK_SERVICE_NAME_SET));
Operation copy = copy(op);
assertSame(DUMMY_SERVICE_NAME, copy.getServiceName());
assertNull(copy.getRawServiceName());
assertFalse("service name should not be set", copy.isFlagSet(Operation.BITMASK_SERVICE_NAME_SET));
}
@Test
public void test_serviceName_whenNotOverridesServiceName_thenSerialized() {
DummyOperation op = new DummyOperation();
op.setServiceName(DUMMY_SERVICE_NAME);
assertSame(DUMMY_SERVICE_NAME, op.getRawServiceName());
assertSame(DUMMY_SERVICE_NAME, op.getServiceName());
assertTrue("service name should be set", op.isFlagSet(Operation.BITMASK_SERVICE_NAME_SET));
Operation copy = copy(op);
assertCopy(DUMMY_SERVICE_NAME, copy.getServiceName());
assertCopy(DUMMY_SERVICE_NAME, copy.getRawServiceName());
assertTrue("service name should be set", copy.isFlagSet(Operation.BITMASK_SERVICE_NAME_SET));
}
private Operation copy(Operation op) {
try {
BufferObjectDataOutput out = serializationService.createObjectDataOutput(1000);
op.writeData(out);
BufferObjectDataInput in = serializationService.createObjectDataInput(out.toByteArray());
Constructor constructor = op.getClass().getConstructor();
constructor.setAccessible(true);
Operation copiedOperation = (Operation) constructor.newInstance();
copiedOperation.readData(in);
return copiedOperation;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void assertCopy(String expected, String actual) {
assertEquals(expected, actual);
assertNotSame(expected, actual);
}
private static class DummyOperation extends Operation {
public DummyOperation() {
}
@Override
public void run() throws Exception {
}
}
private static class OperationWithServiceNameOverride extends Operation {
public OperationWithServiceNameOverride() {
}
@Override
public void run() throws Exception {
}
@Override
public String getServiceName() {
return DUMMY_SERVICE_NAME;
}
}
}