GEODE-2996: incorporating review feedback and adding integration test Addresses review feedback for GEODE-2996, mainly refactoring getOpertionHandler to handle failures like the putOperationHandler Adding put operations to the RoundTripCacheConnectionJUnitTest, which is the integration test for the protobuf module Removing service loading for protobuf operations and instead have the ProtobufStreamProcessor populate its OperationHandlerRegistry Remove exception throwing from OperationHandler.process calls and remove TypeEncodingException
Signed-off-by: Brian Rowe <br...@pivotal.io> Signed-off-by: Alexander Murmann <amurm...@pivotal.io> This closes #605 Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/565e61f7 Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/565e61f7 Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/565e61f7 Branch: refs/heads/feature/GEODE-3109 Commit: 565e61f74409d59cc96c9fbf1ad75d331b728301 Parents: 06961ec Author: Alexander Murmann <amurm...@pivotal.io> Authored: Mon Jun 26 17:56:06 2017 -0700 Committer: Hitesh Khamesra <hkhame...@pivotal.io> Committed: Tue Jun 27 14:48:32 2017 -0700 ---------------------------------------------------------------------- .../protocol/operations/OperationHandler.java | 14 +- .../registry/OperationsHandlerRegistry.java | 7 - .../protocol/protobuf/ProtobufOpsProcessor.java | 29 +++- .../protobuf/ProtobufStreamProcessor.java | 22 ++- .../protocol/protobuf/ProtobufUtilities.java | 11 ++ .../operations/GetRequestOperationHandler.java | 51 ++++--- .../operations/PutRequestOperationHandler.java | 62 +++++++++ .../exception/TypeEncodingException.java | 21 --- .../UnsupportedEncodingTypeException.java | 2 +- .../CodecNotRegisteredForTypeException.java | 4 +- geode-protobuf/src/main/proto/region_API.proto | 4 +- .../org/apache/geode/protocol/MessageUtil.java | 65 +++++++++ .../RoundTripCacheConnectionJUnitTest.java | 45 ++++-- .../protobuf/ProtobufOpsProcessorJUnitTest.java | 7 +- .../GetRequestOperationHandlerJUnitTest.java | 79 +++++++---- .../PutRequestOperationHandlerJUnitTest.java | 139 +++++++++++++++++++ 16 files changed, 440 insertions(+), 122 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/OperationHandler.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/OperationHandler.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/OperationHandler.java index 7683e3b..90fe177 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/OperationHandler.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/OperationHandler.java @@ -15,10 +15,8 @@ package org.apache.geode.protocol.operations; import org.apache.geode.cache.Cache; -import org.apache.geode.protocol.operations.registry.OperationsHandlerRegistry; import org.apache.geode.protocol.protobuf.ProtobufOpsProcessor; import org.apache.geode.serialization.SerializationService; -import org.apache.geode.serialization.exception.TypeEncodingException; /** * This interface is implemented by a object capable of handling request types 'Req' and returning @@ -30,16 +28,6 @@ public interface OperationHandler<Req, Resp> { /** * Decode the message, deserialize contained values using the serialization service, do the work * indicated on the provided cache, and return a response. - * - * @throws TypeEncodingException if a problem occurs decoding an encoded value contained in the - * request. */ - Resp process(SerializationService serializationService, Req request, Cache cache) - throws TypeEncodingException; - - /** - * @return the magic number used for registering the operation type with the - * {@link OperationsHandlerRegistry}. - */ - int getOperationCode(); + Resp process(SerializationService serializationService, Req request, Cache cache); } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/registry/OperationsHandlerRegistry.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/registry/OperationsHandlerRegistry.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/registry/OperationsHandlerRegistry.java index 8e3a331..2b9f525 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/registry/OperationsHandlerRegistry.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/operations/registry/OperationsHandlerRegistry.java @@ -27,13 +27,6 @@ import java.util.ServiceLoader; public class OperationsHandlerRegistry { private HashMap<Integer, OperationHandler> registeredOperations = new HashMap<>(); - public OperationsHandlerRegistry() throws OperationHandlerAlreadyRegisteredException { - ServiceLoader<OperationHandler> operationHandlers = ServiceLoader.load(OperationHandler.class); - for (OperationHandler operationHandler : operationHandlers) { - registerOperationHandlerForOperationId(operationHandler.getOperationCode(), operationHandler); - } - } - public OperationHandler getOperationHandlerForOperationId(int operationCode) throws OperationHandlerNotRegisteredException { OperationHandler operationHandler = registeredOperations.get(operationCode); http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java index d426149..29d3317 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java @@ -20,7 +20,6 @@ import org.apache.geode.protocol.operations.OperationHandler; import org.apache.geode.protocol.operations.registry.OperationsHandlerRegistry; import org.apache.geode.protocol.operations.registry.exception.OperationHandlerNotRegisteredException; import org.apache.geode.serialization.SerializationService; -import org.apache.geode.serialization.exception.TypeEncodingException; /** * This handles protobuf requests by determining the operation type of the request and dispatching @@ -37,15 +36,14 @@ public class ProtobufOpsProcessor { } public ClientProtocol.Response process(ClientProtocol.Request request, Cache cache) - throws TypeEncodingException, OperationHandlerNotRegisteredException, - InvalidProtocolMessageException { - OperationHandler opsHandler = opsHandlerRegistry - .getOperationHandlerForOperationId(request.getRequestAPICase().getNumber()); + throws OperationHandlerNotRegisteredException, InvalidProtocolMessageException { + ClientProtocol.Request.RequestAPICase requestType = request.getRequestAPICase(); + OperationHandler opsHandler = + opsHandlerRegistry.getOperationHandlerForOperationId(requestType.getNumber()); Object responseMessage = opsHandler.process(serializationService, getRequestForOperationTypeID(request), cache); - return ClientProtocol.Response.newBuilder() - .setGetResponse((RegionAPI.GetResponse) responseMessage).build(); + return wrapResponseForOperationTypeID(requestType, responseMessage); } // package visibility for testing @@ -63,4 +61,21 @@ public class ProtobufOpsProcessor { "Unknown request type: " + request.getRequestAPICase().getNumber()); } } + + static ClientProtocol.Response wrapResponseForOperationTypeID( + ClientProtocol.Request.RequestAPICase requestType, Object response) + throws InvalidProtocolMessageException { + ClientProtocol.Response.Builder builder = ClientProtocol.Response.newBuilder(); + switch (requestType) { + case PUTREQUEST: + return builder.setPutResponse((RegionAPI.PutResponse) response).build(); + case GETREQUEST: + return builder.setGetResponse((RegionAPI.GetResponse) response).build(); + case PUTALLREQUEST: + return builder.setPutAllResponse((RegionAPI.PutAllResponse) response).build(); + default: + throw new InvalidProtocolMessageException( + "Unknown request type: " + requestType.getNumber()); + } + } } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java index d7b5d4b..21dbef5 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java @@ -18,14 +18,13 @@ import org.apache.geode.cache.Cache; import org.apache.geode.internal.cache.InternalCache; import org.apache.geode.internal.cache.tier.sockets.ClientProtocolMessageHandler; import org.apache.geode.protocol.exception.InvalidProtocolMessageException; +import org.apache.geode.protocol.protobuf.operations.GetRequestOperationHandler; +import org.apache.geode.protocol.protobuf.operations.PutRequestOperationHandler; import org.apache.geode.protocol.protobuf.serializer.ProtobufProtocolSerializer; import org.apache.geode.protocol.operations.registry.OperationsHandlerRegistry; import org.apache.geode.protocol.operations.registry.exception.OperationHandlerAlreadyRegisteredException; import org.apache.geode.protocol.operations.registry.exception.OperationHandlerNotRegisteredException; -import org.apache.geode.serialization.exception.TypeEncodingException; -import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException; -import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; import java.io.IOException; import java.io.InputStream; @@ -46,13 +45,23 @@ public class ProtobufStreamProcessor implements ClientProtocolMessageHandler { throws OperationHandlerAlreadyRegisteredException, CodecAlreadyRegisteredForTypeException { protobufProtocolSerializer = new ProtobufProtocolSerializer(); registry = new OperationsHandlerRegistry(); + addOperationHandlers(registry); protobufSerializationService = new ProtobufSerializationService(); protobufOpsProcessor = new ProtobufOpsProcessor(registry, protobufSerializationService); } + private void addOperationHandlers(OperationsHandlerRegistry registry) + throws OperationHandlerAlreadyRegisteredException { + registry.registerOperationHandlerForOperationId( + ClientProtocol.Request.RequestAPICase.GETREQUEST.getNumber(), + new GetRequestOperationHandler()); + registry.registerOperationHandlerForOperationId( + ClientProtocol.Request.RequestAPICase.PUTREQUEST.getNumber(), + new PutRequestOperationHandler()); + } + public void processOneMessage(InputStream inputStream, OutputStream outputStream, Cache cache) - throws InvalidProtocolMessageException, OperationHandlerNotRegisteredException, - TypeEncodingException, IOException { + throws InvalidProtocolMessageException, OperationHandlerNotRegisteredException, IOException { ClientProtocol.Message message = protobufProtocolSerializer.deserialize(inputStream); ClientProtocol.Request request = message.getRequest(); @@ -68,8 +77,7 @@ public class ProtobufStreamProcessor implements ClientProtocolMessageHandler { InternalCache cache) throws IOException { try { processOneMessage(inputStream, outputStream, cache); - } catch (InvalidProtocolMessageException | OperationHandlerNotRegisteredException - | TypeEncodingException e) { + } catch (InvalidProtocolMessageException | OperationHandlerNotRegisteredException e) { throw new IOException(e); } } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufUtilities.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufUtilities.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufUtilities.java index d763662..c92da67 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufUtilities.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufUtilities.java @@ -18,6 +18,9 @@ import com.google.protobuf.ByteString; import org.apache.geode.protocol.protobuf.BasicTypes; import org.apache.geode.protocol.protobuf.ClientProtocol; +import org.apache.geode.serialization.SerializationService; +import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; +import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; public abstract class ProtobufUtilities { public static BasicTypes.EncodedValue getEncodedValue(BasicTypes.EncodingType resultEncodingType, @@ -31,4 +34,12 @@ public abstract class ProtobufUtilities { return ClientProtocol.Message.newBuilder() .setMessageHeader(ClientProtocol.MessageHeader.newBuilder()).setResponse(response).build(); } + + public static Object decodeValue(SerializationService serializationService, + BasicTypes.EncodedValue encodedValue) + throws UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { + BasicTypes.EncodingType encoding = encodedValue.getEncodingType(); + byte[] bytes = encodedValue.getValue().toByteArray(); + return serializationService.decode(encoding, bytes); + } } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandler.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandler.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandler.java index d9c1475..95026e8 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandler.java +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandler.java @@ -19,11 +19,9 @@ import org.apache.geode.cache.Cache; import org.apache.geode.cache.Region; import org.apache.geode.protocol.operations.OperationHandler; import org.apache.geode.protocol.protobuf.BasicTypes; -import org.apache.geode.protocol.protobuf.ClientProtocol; import org.apache.geode.protocol.protobuf.RegionAPI; import org.apache.geode.serialization.SerializationService; import org.apache.geode.protocol.protobuf.EncodingTypeTranslator; -import org.apache.geode.serialization.exception.TypeEncodingException; import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; @@ -32,31 +30,52 @@ public class GetRequestOperationHandler @Override public RegionAPI.GetResponse process(SerializationService serializationService, - RegionAPI.GetRequest request, Cache cache) throws TypeEncodingException { + RegionAPI.GetRequest request, Cache cache) { String regionName = request.getRegionName(); - BasicTypes.EncodedValue key = request.getKey(); - BasicTypes.EncodingType encodingType = key.getEncodingType(); - byte[] value = key.getValue().toByteArray(); - Object decodedValue = serializationService.decode(encodingType, value); + try { + Object decodedKey = ProtobufUtilities.decodeValue(serializationService, request.getKey()); - Region region = cache.getRegion(regionName); - Object resultValue = region.get(decodedValue); - return buildGetResponse(serializationService, resultValue); + Region region = cache.getRegion(regionName); + + if (region == null) { + return buildGetResponseFailure(); + } + + Object resultValue = region.get(decodedKey); + + if (resultValue == null) { + return buildGetResponseKeyNotFound(); + } + + return buildGetResponseSuccess(serializationService, resultValue); + } catch (UnsupportedEncodingTypeException ex) { + // can be thrown by encoding or decoding. + cache.getLogger().error("encoding not supported ", ex); + } catch (CodecNotRegisteredForTypeException ex) { + cache.getLogger().error("codec error in protobuf deserialization ", ex); + } + return buildGetResponseFailure(); } - @Override - public int getOperationCode() { - return ClientProtocol.Request.RequestAPICase.GETREQUEST.getNumber(); + private RegionAPI.GetResponse buildGetResponseKeyNotFound() { + return RegionAPI.GetResponse.newBuilder().setSuccess(true).setKeyExists(false).build(); + } + + private RegionAPI.GetResponse buildGetResponseFailure() { + return RegionAPI.GetResponse.newBuilder().setSuccess(false).build(); } - private RegionAPI.GetResponse buildGetResponse(SerializationService serializationService, - Object resultValue) throws TypeEncodingException { + // throws if the object in the cache is not of a class that be serialized via the protobuf + // protocol. + private RegionAPI.GetResponse buildGetResponseSuccess(SerializationService serializationService, + Object resultValue) + throws UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { BasicTypes.EncodingType resultEncodingType = EncodingTypeTranslator.getEncodingTypeForObject(resultValue); byte[] resultEncodedValue = serializationService.encode(resultEncodingType, resultValue); - return RegionAPI.GetResponse.newBuilder() + return RegionAPI.GetResponse.newBuilder().setSuccess(true).setKeyExists(true) .setResult(ProtobufUtilities.getEncodedValue(resultEncodingType, resultEncodedValue)) .build(); } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandler.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandler.java b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandler.java new file mode 100644 index 0000000..f375244 --- /dev/null +++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandler.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.protocol.protobuf.operations; + +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.Region; +import org.apache.geode.protocol.operations.OperationHandler; +import org.apache.geode.protocol.protobuf.BasicTypes; +import org.apache.geode.protocol.protobuf.ClientProtocol; +import org.apache.geode.protocol.protobuf.ProtobufUtilities; +import org.apache.geode.protocol.protobuf.RegionAPI; +import org.apache.geode.serialization.SerializationService; +import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; +import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; + +public class PutRequestOperationHandler + implements OperationHandler<RegionAPI.PutRequest, RegionAPI.PutResponse> { + + @Override + public RegionAPI.PutResponse process(SerializationService serializationService, + RegionAPI.PutRequest request, Cache cache) { + try { + String regionName = request.getRegionName(); + BasicTypes.Entry entry = request.getEntry(); + + Object decodedValue = ProtobufUtilities.decodeValue(serializationService, entry.getValue()); + Object decodedKey = ProtobufUtilities.decodeValue(serializationService, entry.getKey()); + + Region region = cache.getRegion(regionName); + if (region == null) { + cache.getLogger().error("Region passed by client did not exist:" + region); + } else { + try { + region.put(decodedKey, decodedValue); + return RegionAPI.PutResponse.newBuilder().setSuccess(true).build(); + } catch (ClassCastException ex) { + cache.getLogger() + .error("invalid key or value type for region " + regionName + ",passed key: " + + entry.getKey().getEncodingType() + " value: " + + entry.getValue().getEncodingType(), ex); + } + } + } catch (UnsupportedEncodingTypeException ex) { + cache.getLogger().error("encoding not supported ", ex); + } catch (CodecNotRegisteredForTypeException ex) { + cache.getLogger().error("codec error in protobuf deserialization ", ex); + } + return RegionAPI.PutResponse.newBuilder().setSuccess(false).build(); + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/TypeEncodingException.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/TypeEncodingException.java b/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/TypeEncodingException.java deleted file mode 100644 index f3145a7..0000000 --- a/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/TypeEncodingException.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.serialization.exception; - -public class TypeEncodingException extends Exception { - public TypeEncodingException(String message) { - super(message); - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/UnsupportedEncodingTypeException.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/UnsupportedEncodingTypeException.java b/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/UnsupportedEncodingTypeException.java index c577e76..6d2a032 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/UnsupportedEncodingTypeException.java +++ b/geode-protobuf/src/main/java/org/apache/geode/serialization/exception/UnsupportedEncodingTypeException.java @@ -17,7 +17,7 @@ package org.apache.geode.serialization.exception; /** * This indicates an encoding type that we don't know how to handle. */ -public class UnsupportedEncodingTypeException extends TypeEncodingException { +public class UnsupportedEncodingTypeException extends Exception { public UnsupportedEncodingTypeException(String message) { super(message); } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/java/org/apache/geode/serialization/registry/exception/CodecNotRegisteredForTypeException.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/java/org/apache/geode/serialization/registry/exception/CodecNotRegisteredForTypeException.java b/geode-protobuf/src/main/java/org/apache/geode/serialization/registry/exception/CodecNotRegisteredForTypeException.java index 5c923a5..58cb691 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/serialization/registry/exception/CodecNotRegisteredForTypeException.java +++ b/geode-protobuf/src/main/java/org/apache/geode/serialization/registry/exception/CodecNotRegisteredForTypeException.java @@ -14,12 +14,10 @@ */ package org.apache.geode.serialization.registry.exception; -import org.apache.geode.serialization.exception.TypeEncodingException; - /** * This indicates we're attempting to handle a type for which we don't have a registered codec. */ -public class CodecNotRegisteredForTypeException extends TypeEncodingException { +public class CodecNotRegisteredForTypeException extends Exception { public CodecNotRegisteredForTypeException(String message) { super(message); } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/main/proto/region_API.proto ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/main/proto/region_API.proto b/geode-protobuf/src/main/proto/region_API.proto index 52291c4..adeb011 100644 --- a/geode-protobuf/src/main/proto/region_API.proto +++ b/geode-protobuf/src/main/proto/region_API.proto @@ -33,7 +33,9 @@ message GetRequest { } message GetResponse { - EncodedValue result = 1; + bool success = 1; + bool keyExists = 2; + EncodedValue result = 3; } message PutAllRequest { http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/test/java/org/apache/geode/protocol/MessageUtil.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/MessageUtil.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/MessageUtil.java index f0b0b41..73d0803 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/protocol/MessageUtil.java +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/MessageUtil.java @@ -14,8 +14,19 @@ */ package org.apache.geode.protocol; +import com.google.protobuf.ByteString; + +import org.apache.geode.protocol.protobuf.BasicTypes; import org.apache.geode.protocol.protobuf.ClientProtocol; +import org.apache.geode.protocol.protobuf.EncodingTypeTranslator; import org.apache.geode.protocol.protobuf.RegionAPI; +import org.apache.geode.serialization.codec.StringCodec; +import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; +import org.apache.geode.serialization.registry.SerializationCodecRegistry; +import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException; +import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; + +import java.nio.ByteBuffer; public class MessageUtil { public static ClientProtocol.Message createGetRequestMessage() { @@ -27,6 +38,60 @@ public class MessageUtil { return messageBuilder.build(); } + public static RegionAPI.PutRequest makePutRequest(String requestKey, String requestValue, + String requestRegion) throws CodecNotRegisteredForTypeException, + UnsupportedEncodingTypeException, CodecAlreadyRegisteredForTypeException { + StringCodec stringCodec = getStringCodec(); + BasicTypes.EncodedValue.Builder key = + BasicTypes.EncodedValue.newBuilder().setEncodingType(BasicTypes.EncodingType.STRING) + .setValue(ByteString.copyFrom(stringCodec.encode(requestKey))); + BasicTypes.EncodedValue.Builder value = + BasicTypes.EncodedValue.newBuilder().setEncodingType(BasicTypes.EncodingType.STRING) + .setValue(ByteString.copyFrom(stringCodec.encode(requestValue))); + BasicTypes.Entry.Builder entry = BasicTypes.Entry.newBuilder().setKey(key).setValue(value); + RegionAPI.PutRequest.Builder putRequestBuilder = RegionAPI.PutRequest.newBuilder(); + putRequestBuilder.setRegionName(requestRegion).setEntry(entry); + + return putRequestBuilder.build(); + } + + public static ClientProtocol.Message makePutRequestMessage(String requestKey, String requestValue, + String requestRegion, ClientProtocol.MessageHeader header) + throws CodecNotRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecAlreadyRegisteredForTypeException { + ClientProtocol.Request request = ClientProtocol.Request.newBuilder() + .setPutRequest(makePutRequest(requestKey, requestValue, requestRegion)).build(); + return ClientProtocol.Message.newBuilder().setMessageHeader(header).setRequest(request).build(); + } + + public static RegionAPI.GetRequest makeGetRequest(String requestKey, String requestRegion) + throws CodecNotRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecAlreadyRegisteredForTypeException { + StringCodec stringCodec = getStringCodec(); + RegionAPI.GetRequest.Builder getRequestBuilder = RegionAPI.GetRequest.newBuilder(); + getRequestBuilder.setRegionName(requestRegion) + .setKey(BasicTypes.EncodedValue.newBuilder().setEncodingType(BasicTypes.EncodingType.STRING) + .setValue(ByteString.copyFrom(stringCodec.encode(requestKey)))); + + return getRequestBuilder.build(); + } + + public static ClientProtocol.Message makeGetRequestMessage(String requestKey, + String requestRegion, ClientProtocol.MessageHeader header) + throws CodecAlreadyRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException { + ClientProtocol.Request request = ClientProtocol.Request.newBuilder() + .setGetRequest(makeGetRequest(requestKey, requestRegion)).build(); + return ClientProtocol.Message.newBuilder().setMessageHeader(header).setRequest(request).build(); + } + + public static StringCodec getStringCodec() throws CodecAlreadyRegisteredForTypeException, + CodecNotRegisteredForTypeException, UnsupportedEncodingTypeException { + SerializationCodecRegistry serializationCodecRegistry = new SerializationCodecRegistry(); + return (StringCodec) serializationCodecRegistry.getCodecForType( + EncodingTypeTranslator.getSerializationTypeForEncodingType(BasicTypes.EncodingType.STRING)); + } + private static ClientProtocol.Request.Builder getRequestBuilder() { return ClientProtocol.Request.newBuilder(); } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java index b9faca3..1fbe821 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/RoundTripCacheConnectionJUnitTest.java @@ -26,12 +26,16 @@ import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.server.CacheServer; import org.apache.geode.internal.AvailablePortHelper; import org.apache.geode.internal.cache.tier.sockets.GenericProtocolServerConnection; +import org.apache.geode.protocol.exception.InvalidProtocolMessageException; import org.apache.geode.protocol.protobuf.BasicTypes; import org.apache.geode.protocol.protobuf.ClientProtocol; import org.apache.geode.protocol.protobuf.ProtobufSerializationService; import org.apache.geode.protocol.protobuf.RegionAPI; import org.apache.geode.protocol.protobuf.serializer.ProtobufProtocolSerializer; import org.apache.geode.serialization.codec.StringCodec; +import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; +import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException; +import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; import org.apache.geode.test.junit.categories.IntegrationTest; import org.awaitility.Awaitility; import org.junit.After; @@ -75,7 +79,6 @@ public class RoundTripCacheConnectionJUnitTest { RegionFactory<Object, Object> regionFactory = cache.createRegionFactory(); Region<Object, Object> testRegion = regionFactory.create(TEST_REGION); - testRegion.put(TEST_KEY, TEST_VALUE); } @After @@ -93,8 +96,33 @@ public class RoundTripCacheConnectionJUnitTest { outputStream.write(110); ProtobufProtocolSerializer protobufProtocolSerializer = new ProtobufProtocolSerializer(); - protobufProtocolSerializer.serialize(makeTestGetRequest(new StringCodec()), outputStream); + ClientProtocol.Message putMessage = MessageUtil.makePutRequestMessage(TEST_KEY, TEST_VALUE, + TEST_REGION, ClientProtocol.MessageHeader.newBuilder().build()); + protobufProtocolSerializer.serialize(putMessage, outputStream); + validatePutResponse(socket, protobufProtocolSerializer); + + ClientProtocol.Message getMessage = MessageUtil.makeGetRequestMessage(TEST_KEY, TEST_REGION, + ClientProtocol.MessageHeader.newBuilder().build()); + protobufProtocolSerializer.serialize(getMessage, outputStream); + validateGetResponse(socket, protobufProtocolSerializer); + } + + private void validatePutResponse(Socket socket, + ProtobufProtocolSerializer protobufProtocolSerializer) throws Exception { + ClientProtocol.Message message = + protobufProtocolSerializer.deserialize(socket.getInputStream()); + assertEquals(ClientProtocol.Message.MessageTypeCase.RESPONSE, message.getMessageTypeCase()); + ClientProtocol.Response response = message.getResponse(); + assertEquals(ClientProtocol.Response.ResponseAPICase.PUTRESPONSE, + response.getResponseAPICase()); + RegionAPI.PutResponse putResponse = response.getPutResponse(); + assertEquals(true, putResponse.getSuccess()); + } + private void validateGetResponse(Socket socket, + ProtobufProtocolSerializer protobufProtocolSerializer) + throws InvalidProtocolMessageException, IOException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException, CodecAlreadyRegisteredForTypeException { ClientProtocol.Message message = protobufProtocolSerializer.deserialize(socket.getInputStream()); assertEquals(ClientProtocol.Message.MessageTypeCase.RESPONSE, message.getMessageTypeCase()); @@ -107,17 +135,4 @@ public class RoundTripCacheConnectionJUnitTest { assertEquals(TEST_VALUE, new ProtobufSerializationService().decode(result.getEncodingType(), result.getValue().toByteArray())); } - - private ClientProtocol.Message makeTestGetRequest(StringCodec stringCodec) { - RegionAPI.GetRequest.Builder getRequestBuilder = RegionAPI.GetRequest.newBuilder(); - getRequestBuilder.setRegionName(TEST_REGION) - .setKey(BasicTypes.EncodedValue.newBuilder().setEncodingType(BasicTypes.EncodingType.STRING) - .setValue(ByteString.copyFrom(stringCodec.encode(TEST_KEY)))); - ClientProtocol.Request request = - ClientProtocol.Request.newBuilder().setGetRequest(getRequestBuilder).build(); - ClientProtocol.Message requestMessage = ClientProtocol.Message.newBuilder() - .setMessageHeader(ClientProtocol.MessageHeader.newBuilder()).setRequest(request).build(); - - return requestMessage; - } } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessorJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessorJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessorJUnitTest.java index fc980ae..c51be5c 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessorJUnitTest.java +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessorJUnitTest.java @@ -24,9 +24,6 @@ import org.apache.geode.protocol.operations.OperationHandler; import org.apache.geode.protocol.operations.registry.OperationsHandlerRegistry; import org.apache.geode.protocol.operations.registry.exception.OperationHandlerNotRegisteredException; import org.apache.geode.serialization.SerializationService; -import org.apache.geode.serialization.exception.TypeEncodingException; -import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; -import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; import org.apache.geode.test.junit.categories.UnitTest; import org.junit.Assert; import org.junit.Test; @@ -35,8 +32,8 @@ import org.junit.experimental.categories.Category; @Category(UnitTest.class) public class ProtobufOpsProcessorJUnitTest { @Test - public void testOpsProcessor() throws TypeEncodingException, - OperationHandlerNotRegisteredException, InvalidProtocolMessageException { + public void testOpsProcessor() + throws OperationHandlerNotRegisteredException, InvalidProtocolMessageException { OperationsHandlerRegistry opsHandlerRegistryStub = mock(OperationsHandlerRegistry.class); OperationHandler operationHandlerStub = mock(OperationHandler.class); SerializationService serializationServiceStub = mock(SerializationService.class); http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandlerJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandlerJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandlerJUnitTest.java index daa5870..f92b194 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandlerJUnitTest.java +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/GetRequestOperationHandlerJUnitTest.java @@ -14,19 +14,14 @@ */ package org.apache.geode.protocol.protobuf.operations; -import com.google.protobuf.ByteString; - +import org.apache.geode.LogWriter; import org.apache.geode.cache.Cache; import org.apache.geode.cache.Region; +import org.apache.geode.protocol.MessageUtil; import org.apache.geode.protocol.protobuf.BasicTypes; import org.apache.geode.protocol.protobuf.RegionAPI; -import org.apache.geode.protocol.protobuf.operations.GetRequestOperationHandler; import org.apache.geode.serialization.SerializationService; -import org.apache.geode.serialization.codec.StringCodec; -import org.apache.geode.protocol.protobuf.EncodingTypeTranslator; -import org.apache.geode.serialization.exception.TypeEncodingException; import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; -import org.apache.geode.serialization.registry.SerializationCodecRegistry; import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException; import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; import org.apache.geode.test.dunit.Assert; @@ -37,7 +32,10 @@ import org.junit.experimental.categories.Category; import java.nio.charset.Charset; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @Category(UnitTest.class) @@ -45,8 +43,11 @@ public class GetRequestOperationHandlerJUnitTest { public static final String TEST_KEY = "my key"; public static final String TEST_VALUE = "my value"; public static final String TEST_REGION = "test region"; + public static final String MISSING_REGION = "missing region"; + public static final String MISSING_KEY = "missing key"; public Cache cacheStub; public SerializationService serializationServiceStub; + private GetRequestOperationHandler operationHandler; @Before public void setUp() throws Exception { @@ -61,36 +62,62 @@ public class GetRequestOperationHandlerJUnitTest { cacheStub = mock(Cache.class); when(cacheStub.getRegion(TEST_REGION)).thenReturn(regionStub); + when(cacheStub.getRegion(MISSING_REGION)).thenReturn(null); + operationHandler = new GetRequestOperationHandler(); } @Test public void processReturnsTheEncodedValueFromTheRegion() - throws TypeEncodingException, CodecAlreadyRegisteredForTypeException { - GetRequestOperationHandler operationHandler = new GetRequestOperationHandler(); - - RegionAPI.GetResponse response = - operationHandler.process(serializationServiceStub, makeGetRequest(), cacheStub); + throws CodecAlreadyRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException { + RegionAPI.GetResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makeGetRequest(TEST_KEY, TEST_REGION), cacheStub); + Assert.assertEquals(true, response.getSuccess()); + Assert.assertEquals(true, response.getKeyExists()); Assert.assertEquals(BasicTypes.EncodingType.STRING, response.getResult().getEncodingType()); - String actualValue = getStringCodec().decode(response.getResult().getValue().toByteArray()); + String actualValue = + MessageUtil.getStringCodec().decode(response.getResult().getValue().toByteArray()); Assert.assertEquals(TEST_VALUE, actualValue); } - private RegionAPI.GetRequest makeGetRequest() throws CodecNotRegisteredForTypeException, - UnsupportedEncodingTypeException, CodecAlreadyRegisteredForTypeException { - StringCodec stringCodec = getStringCodec(); - RegionAPI.GetRequest.Builder getRequestBuilder = RegionAPI.GetRequest.newBuilder(); - getRequestBuilder.setRegionName(TEST_REGION) - .setKey(BasicTypes.EncodedValue.newBuilder().setEncodingType(BasicTypes.EncodingType.STRING) - .setValue(ByteString.copyFrom(stringCodec.encode(TEST_KEY)))); + @Test + public void processReturnsUnsucessfulResponseForInvalidRegion() + throws CodecAlreadyRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException { + RegionAPI.GetResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makeGetRequest(TEST_KEY, MISSING_REGION), cacheStub); + + Assert.assertEquals(false, response.getSuccess()); + } + + @Test + public void processReturnsKeyNotFoundWhenKeyIsNotFound() + throws CodecAlreadyRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException { + RegionAPI.GetResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makeGetRequest(MISSING_KEY, TEST_REGION), cacheStub); - return getRequestBuilder.build(); + Assert.assertEquals(true, response.getSuccess()); + Assert.assertEquals(false, response.getKeyExists()); } - private StringCodec getStringCodec() throws CodecAlreadyRegisteredForTypeException, - CodecNotRegisteredForTypeException, UnsupportedEncodingTypeException { - SerializationCodecRegistry serializationCodecRegistry = new SerializationCodecRegistry(); - return (StringCodec) serializationCodecRegistry.getCodecForType( - EncodingTypeTranslator.getSerializationTypeForEncodingType(BasicTypes.EncodingType.STRING)); + @Test + public void processReturnsErrorWhenUnableToDecodeRequest() + throws CodecAlreadyRegisteredForTypeException, UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException { + LogWriter loggerMock = mock(LogWriter.class); + when(cacheStub.getLogger()).thenReturn(loggerMock); + + CodecNotRegisteredForTypeException exception = + new CodecNotRegisteredForTypeException("error finding codec for type"); + when(serializationServiceStub.decode(BasicTypes.EncodingType.STRING, + TEST_KEY.getBytes(Charset.forName("UTF-8")))).thenThrow(exception); + + RegionAPI.GetResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makeGetRequest(TEST_KEY, TEST_REGION), cacheStub); + + Assert.assertEquals(false, response.getSuccess()); + verify(loggerMock).error(any(String.class), eq(exception)); } } http://git-wip-us.apache.org/repos/asf/geode/blob/565e61f7/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandlerJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandlerJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandlerJUnitTest.java new file mode 100644 index 0000000..ddc23fc --- /dev/null +++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/operations/PutRequestOperationHandlerJUnitTest.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.protocol.protobuf.operations; + +import com.google.protobuf.ByteString; +import org.apache.geode.LogWriter; +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.Region; +import org.apache.geode.protocol.MessageUtil; +import org.apache.geode.protocol.protobuf.BasicTypes; +import org.apache.geode.protocol.protobuf.EncodingTypeTranslator; +import org.apache.geode.protocol.protobuf.RegionAPI; +import org.apache.geode.serialization.SerializationService; +import org.apache.geode.serialization.codec.StringCodec; +import org.apache.geode.serialization.exception.UnsupportedEncodingTypeException; +import org.apache.geode.serialization.registry.SerializationCodecRegistry; +import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException; +import org.apache.geode.serialization.registry.exception.CodecNotRegisteredForTypeException; +import org.apache.geode.test.dunit.Assert; +import org.apache.geode.test.junit.categories.UnitTest; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +import static org.mockito.Mockito.*; + +@Category(UnitTest.class) +public class PutRequestOperationHandlerJUnitTest { + public static final String TEST_KEY = "my key"; + public static final String TEST_VALUE = "99"; + public static final String TEST_REGION = "test region"; + public Cache cacheStub; + public SerializationService serializationServiceStub; + private Region regionMock; + private LogWriter loggerMock; + + @Before + public void setUp() throws Exception { + serializationServiceStub = mock(SerializationService.class); + when(serializationServiceStub.decode(BasicTypes.EncodingType.STRING, + TEST_KEY.getBytes(Charset.forName("UTF-8")))).thenReturn(TEST_KEY); + when(serializationServiceStub.decode(BasicTypes.EncodingType.STRING, + TEST_VALUE.getBytes(Charset.forName("UTF-8")))).thenReturn(TEST_VALUE); + + regionMock = mock(Region.class); + when(regionMock.put(TEST_KEY, TEST_VALUE)).thenReturn(1); + + cacheStub = mock(Cache.class); + when(cacheStub.getRegion(TEST_REGION)).thenReturn(regionMock); + + loggerMock = mock(LogWriter.class); + when(cacheStub.getLogger()).thenReturn(loggerMock); + } + + @Test + public void test_puttingTheEncodedEntryIntoRegion() throws UnsupportedEncodingTypeException, + CodecNotRegisteredForTypeException, CodecAlreadyRegisteredForTypeException { + PutRequestOperationHandler operationHandler = new PutRequestOperationHandler(); + + + RegionAPI.PutResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makePutRequest(TEST_KEY, TEST_VALUE, TEST_REGION), cacheStub); + + Assert.assertTrue(response.getSuccess()); + verify(regionMock).put(TEST_KEY, TEST_VALUE); + verify(regionMock, times(1)).put(anyString(), anyString()); + } + + @Test + public void test_invalidEncodingType() throws CodecAlreadyRegisteredForTypeException, + UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { + UnsupportedEncodingTypeException exception = + new UnsupportedEncodingTypeException("unsupported type!"); + when(serializationServiceStub.decode(BasicTypes.EncodingType.STRING, + TEST_KEY.getBytes(Charset.forName("UTF-8")))).thenThrow(exception); + PutRequestOperationHandler operationHandler = new PutRequestOperationHandler(); + + RegionAPI.PutResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makePutRequest(TEST_KEY, TEST_VALUE, TEST_REGION), cacheStub); + + verify(loggerMock).error(any(String.class), eq(exception)); + Assert.assertFalse(response.getSuccess()); + } + + @Test + public void test_codecNotRegistered() throws CodecAlreadyRegisteredForTypeException, + UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { + CodecNotRegisteredForTypeException exception = + new CodecNotRegisteredForTypeException("error finding codec for type"); + when(serializationServiceStub.decode(BasicTypes.EncodingType.STRING, + TEST_KEY.getBytes(Charset.forName("UTF-8")))).thenThrow(exception); + PutRequestOperationHandler operationHandler = new PutRequestOperationHandler(); + + RegionAPI.PutResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makePutRequest(TEST_KEY, TEST_VALUE, TEST_REGION), cacheStub); + + verify(loggerMock).error(any(String.class), eq(exception)); + Assert.assertFalse(response.getSuccess()); + } + + @Test + public void test_RegionNotFound() throws CodecAlreadyRegisteredForTypeException, + UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { + when(cacheStub.getRegion(TEST_REGION)).thenReturn(null); + PutRequestOperationHandler operationHandler = new PutRequestOperationHandler(); + RegionAPI.PutResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makePutRequest(TEST_KEY, TEST_VALUE, TEST_REGION), cacheStub); + + Assert.assertFalse(response.getSuccess()); + } + + @Test + public void test_RegionThrowsClasscastException() throws CodecAlreadyRegisteredForTypeException, + UnsupportedEncodingTypeException, CodecNotRegisteredForTypeException { + when(regionMock.put(any(), any())).thenThrow(ClassCastException.class); + + PutRequestOperationHandler operationHandler = new PutRequestOperationHandler(); + RegionAPI.PutResponse response = operationHandler.process(serializationServiceStub, + MessageUtil.makePutRequest(TEST_KEY, TEST_VALUE, TEST_REGION), cacheStub); + + verify(loggerMock).error(any(String.class), any(ClassCastException.class)); + Assert.assertFalse(response.getSuccess()); + } +}