GetResponse makeGetResponse(GetRequest getRequest, ServerErrorCode getError) throws IOException {
    GetResponse getResponse;
    if (getError == ServerErrorCode.NoError) {
      List<PartitionRequestInfo> infos = getRequest.getPartitionInfoList();
      if (infos.size() != 1 || infos.get(0).getBlobIds().size() != 1) {
        getError = ServerErrorCode.UnknownError;
      }
    }

    ServerErrorCode serverError;
    ServerErrorCode partitionError;
    boolean isDataBlob = false;
    try {
      String id = getRequest.getPartitionInfoList().get(0).getBlobIds().get(0).getID();
      isDataBlob = blobs.get(id).type == BlobType.DataBlob;
    } catch (Exception ignored) {
    }

    if (!getErrorOnDataBlobOnly || isDataBlob) {
      // getError could be at the server level or the partition level. For partition level errors,
      // set it in the partitionResponseInfo
      if (getError == ServerErrorCode.NoError || getError == ServerErrorCode.BlobExpired
          || getError == ServerErrorCode.BlobDeleted || getError == ServerErrorCode.BlobNotFound
          || getError == ServerErrorCode.BlobAuthorizationFailure || getError == ServerErrorCode.DiskUnavailable) {
        partitionError = getError;
        serverError = ServerErrorCode.NoError;
      } else {
        serverError = getError;
        // does not matter - this will not be checked if serverError is not No_Error.
        partitionError = ServerErrorCode.NoError;
      }
    } else {
      serverError = ServerErrorCode.NoError;
      partitionError = ServerErrorCode.NoError;
    }

    if (serverError == ServerErrorCode.NoError) {
      int byteBufferSize;
      ByteBuffer byteBuffer;
      StoreKey key = getRequest.getPartitionInfoList().get(0).getBlobIds().get(0);
      short accountId = Account.UNKNOWN_ACCOUNT_ID;
      short containerId = Container.UNKNOWN_CONTAINER_ID;
      long operationTimeMs = Utils.Infinite_Time;
      StoredBlob blob = blobs.get(key.getID());
      ServerErrorCode processedError = errorForGet(key.getID(), blob, getRequest);
      MessageMetadata msgMetadata = null;
      if (processedError == ServerErrorCode.NoError) {
        ByteBuffer buf = blobs.get(key.getID()).serializedSentPutRequest.duplicate();
        // read off the size
        buf.getLong();
        // read off the type.
        buf.getShort();
        PutRequest originalBlobPutReq =
            PutRequest.readFrom(new DataInputStream(new ByteBufferInputStream(buf)), clusterMap);
        switch (getRequest.getMessageFormatFlag()) {
          case BlobInfo:
            BlobProperties blobProperties = originalBlobPutReq.getBlobProperties();
            accountId = blobProperties.getAccountId();
            containerId = blobProperties.getContainerId();
            operationTimeMs = blobProperties.getCreationTimeInMs();
            ByteBuffer userMetadata = originalBlobPutReq.getUsermetadata();
            byteBufferSize = MessageFormatRecord.BlobProperties_Format_V1.getBlobPropertiesRecordSize(blobProperties)
                + MessageFormatRecord.UserMetadata_Format_V1.getUserMetadataSize(userMetadata);
            byteBuffer = ByteBuffer.allocate(byteBufferSize);
            if (originalBlobPutReq.getBlobEncryptionKey() != null) {
              msgMetadata = new MessageMetadata(originalBlobPutReq.getBlobEncryptionKey().duplicate());
            }
            MessageFormatRecord.BlobProperties_Format_V1.serializeBlobPropertiesRecord(byteBuffer, blobProperties);
            MessageFormatRecord.UserMetadata_Format_V1.serializeUserMetadataRecord(byteBuffer, userMetadata);
            break;
          case Blob:
            switch (blobFormatVersion) {
              case MessageFormatRecord.Blob_Version_V3:
                if (originalBlobPutReq.getBlobEncryptionKey() != null) {
                  msgMetadata = new MessageMetadata(originalBlobPutReq.getBlobEncryptionKey().duplicate());
                }
                byteBufferSize =
                    (int) MessageFormatRecord.Blob_Format_V3.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                byteBuffer = ByteBuffer.allocate(byteBufferSize);
                MessageFormatRecord.Blob_Format_V3.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize(), originalBlobPutReq.getBlobType(),
                    originalBlobPutReq.isCompressed());
                break;
              case MessageFormatRecord.Blob_Version_V2:
                if (originalBlobPutReq.getBlobEncryptionKey() != null) {
                  msgMetadata = new MessageMetadata(originalBlobPutReq.getBlobEncryptionKey().duplicate());
                }
                byteBufferSize =
                    (int) MessageFormatRecord.Blob_Format_V2.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                byteBuffer = ByteBuffer.allocate(byteBufferSize);
                MessageFormatRecord.Blob_Format_V2.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize(), originalBlobPutReq.getBlobType());
                break;
              case MessageFormatRecord.Blob_Version_V1:
                byteBufferSize =
                    (int) MessageFormatRecord.Blob_Format_V1.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                byteBuffer = ByteBuffer.allocate(byteBufferSize);
                MessageFormatRecord.Blob_Format_V1.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize());
                break;
              default:
                throw new IllegalStateException("Blob format version " + blobFormatVersion + " not supported.");
            }
            byteBuffer.put(
                Utils.readBytesFromStream(originalBlobPutReq.getBlobStream(), (int) originalBlobPutReq.getBlobSize()));
            CRC32 crc = new CRC32();
            crc.update(byteBuffer.array(), 0, byteBuffer.position());
            byteBuffer.putLong(crc.getValue());
            break;
          case All:
            blobProperties = originalBlobPutReq.getBlobProperties();
            accountId = blobProperties.getAccountId();
            containerId = blobProperties.getContainerId();
            userMetadata = originalBlobPutReq.getUsermetadata();
            operationTimeMs = originalBlobPutReq.getBlobProperties().getCreationTimeInMs();
            int blobHeaderSize = MessageFormatRecord.MessageHeader_Format_V2.getHeaderSize();
            int blobEncryptionRecordSize = originalBlobPutReq.getBlobEncryptionKey() != null
                ? MessageFormatRecord.BlobEncryptionKey_Format_V1.getBlobEncryptionKeyRecordSize(
                originalBlobPutReq.getBlobEncryptionKey().duplicate()) : 0;
            int blobPropertiesSize =
                MessageFormatRecord.BlobProperties_Format_V1.getBlobPropertiesRecordSize(blobProperties);
            int userMetadataSize = MessageFormatRecord.UserMetadata_Format_V1.getUserMetadataSize(userMetadata);
            int blobInfoSize = blobPropertiesSize + userMetadataSize;
            int blobRecordSize;
            switch (blobFormatVersion) {
              case MessageFormatRecord.Blob_Version_V3:
                blobRecordSize =
                    (int) MessageFormatRecord.Blob_Format_V3.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                break;
              case MessageFormatRecord.Blob_Version_V2:
                blobRecordSize =
                    (int) MessageFormatRecord.Blob_Format_V2.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                break;
              case MessageFormatRecord.Blob_Version_V1:
                blobRecordSize =
                    (int) MessageFormatRecord.Blob_Format_V1.getBlobRecordSize((int) originalBlobPutReq.getBlobSize());
                break;
              default:
                throw new IllegalStateException("Blob format version " + blobFormatVersion + " not supported.");
            }
            byteBufferSize =
                blobHeaderSize + key.sizeInBytes() + blobEncryptionRecordSize + blobInfoSize + blobRecordSize;
            byteBuffer = ByteBuffer.allocate(byteBufferSize);
            try {
              MessageFormatRecord.MessageHeader_Format_V2.serializeHeader(byteBuffer,
                  blobEncryptionRecordSize + blobInfoSize + blobRecordSize,
                  originalBlobPutReq.getBlobEncryptionKey() == null ? Message_Header_Invalid_Relative_Offset
                      : blobHeaderSize + key.sizeInBytes(),
                  blobHeaderSize + key.sizeInBytes() + blobEncryptionRecordSize, Message_Header_Invalid_Relative_Offset,
                  blobHeaderSize + key.sizeInBytes() + blobEncryptionRecordSize + blobPropertiesSize,
                  blobHeaderSize + key.sizeInBytes() + blobEncryptionRecordSize + blobInfoSize);
            } catch (MessageFormatException e) {
              e.printStackTrace();
            }
            byteBuffer.put(key.toBytes());
            if (originalBlobPutReq.getBlobEncryptionKey() != null) {
              MessageFormatRecord.BlobEncryptionKey_Format_V1.serializeBlobEncryptionKeyRecord(byteBuffer,
                  originalBlobPutReq.getBlobEncryptionKey().duplicate());
              msgMetadata = new MessageMetadata(originalBlobPutReq.getBlobEncryptionKey().duplicate());
            }
            MessageFormatRecord.BlobProperties_Format_V1.serializeBlobPropertiesRecord(byteBuffer, blobProperties);
            MessageFormatRecord.UserMetadata_Format_V1.serializeUserMetadataRecord(byteBuffer, userMetadata);
            int blobRecordStart = byteBuffer.position();
            switch (blobFormatVersion) {
              case MessageFormatRecord.Blob_Version_V3:
                MessageFormatRecord.Blob_Format_V3.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize(), originalBlobPutReq.getBlobType(), originalBlobPutReq.isCompressed());
                break;
              case MessageFormatRecord.Blob_Version_V2:
                MessageFormatRecord.Blob_Format_V2.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize(), originalBlobPutReq.getBlobType());
                break;
              case MessageFormatRecord.Blob_Version_V1:
                MessageFormatRecord.Blob_Format_V1.serializePartialBlobRecord(byteBuffer,
                    (int) originalBlobPutReq.getBlobSize());
                break;
              default:
                throw new IllegalStateException("Blob format version " + blobFormatVersion + " not supported.");
            }
            byteBuffer.put(
                Utils.readBytesFromStream(originalBlobPutReq.getBlobStream(), (int) originalBlobPutReq.getBlobSize()));
            crc = new CRC32();
            crc.update(byteBuffer.array(), blobRecordStart, blobRecordSize - MessageFormatRecord.Crc_Size);
            byteBuffer.putLong(crc.getValue());
            break;
          default:
            throw new IOException("GetRequest flag is not supported: " + getRequest.getMessageFormatFlag());
        }
      } else if (processedError == ServerErrorCode.BlobDeleted) {
        if (partitionError == ServerErrorCode.NoError) {
          partitionError = ServerErrorCode.BlobDeleted;
        }
        byteBuffer = ByteBuffer.allocate(0);
        byteBufferSize = 0;
      } else if (processedError == ServerErrorCode.BlobExpired) {
        if (partitionError == ServerErrorCode.NoError) {
          partitionError = ServerErrorCode.BlobExpired;
        }
        byteBuffer = ByteBuffer.allocate(0);
        byteBufferSize = 0;
      } else if (processedError == ServerErrorCode.BlobAuthorizationFailure) {
        if (partitionError == ServerErrorCode.NoError) {
          partitionError = ServerErrorCode.BlobAuthorizationFailure;
        }
        byteBuffer = ByteBuffer.allocate(0);
        byteBufferSize = 0;
      } else if (processedError == ServerErrorCode.ReplicaUnavailable) {
        if (partitionError == ServerErrorCode.NoError) {
          partitionError = ServerErrorCode.ReplicaUnavailable;
        }
        byteBuffer = ByteBuffer.allocate(0);
        byteBufferSize = 0;
      } else {
        if (partitionError == ServerErrorCode.NoError) {
          partitionError = ServerErrorCode.BlobNotFound;
        }
        byteBuffer = ByteBuffer.allocate(0);
        byteBufferSize = 0;
      }

      byteBuffer.flip();
      ByteBufferSend responseSend = new ByteBufferSend(byteBuffer);
      List<MessageInfo> messageInfoList = new ArrayList<>();
      List<MessageMetadata> messageMetadataList = new ArrayList<>();
      List<PartitionResponseInfo> partitionResponseInfoList = new ArrayList<PartitionResponseInfo>();
      if (partitionError == ServerErrorCode.NoError) {
        messageInfoList.add(
            new MessageInfo(key, byteBufferSize, false, blob.isTtlUpdated(), blob.isUndeleted(), blob.expiresAt, null,
                accountId, containerId, operationTimeMs, blob.lifeVersion));
        messageMetadataList.add(msgMetadata);
      }
      PartitionResponseInfo partitionResponseInfo =
          partitionError == ServerErrorCode.NoError ? new PartitionResponseInfo(
              getRequest.getPartitionInfoList().get(0).getPartition(), messageInfoList, messageMetadataList)
              : new PartitionResponseInfo(getRequest.getPartitionInfoList().get(0).getPartition(), partitionError);
      partitionResponseInfoList.add(partitionResponseInfo);
      getResponse = new GetResponse(getRequest.getCorrelationId(), getRequest.getClientId(), partitionResponseInfoList,
          responseSend, serverError);
    } else {
      getResponse = new GetResponse(getRequest.getCorrelationId(), getRequest.getClientId(),
          new ArrayList<PartitionResponseInfo>(), new ByteBufferSend(ByteBuffer.allocate(0)), serverError);
    }
    return getResponse;
  }
Make a {@link GetResponse} for the given {@link GetRequest} for which the given {@link ServerErrorCode} was
encountered. The request could be for BlobInfo or for Blob (the only two options that the router would request
for).
@param getRequest the {@link GetRequest} for which the response is being constructed.
@param getError the {@link ServerErrorCode} that was encountered.
@return the constructed {@link GetResponse}
@throws IOException if there was an error constructing the response.
ambry-router/src/test/java/com/github/ambry/router/MockServer.java