/** * Copyright 2016 LinkedIn Corp. 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. */ package com.github.ambry.commons; import com.github.ambry.clustermap.MockClusterMap; import com.github.ambry.clustermap.MockPartitionId; import com.github.ambry.clustermap.PartitionId; import com.github.ambry.utils.ByteBufferInputStream; import java.io.DataInputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import org.apache.commons.codec.binary.Base64; import org.junit.Test; import static org.junit.Assert.*; public class BlobIdTest { @Test public void basicTest() throws Exception { final long id = 99; PartitionId partitionId = new MockPartitionId(id, Collections.EMPTY_LIST, 0); BlobId blobId = new BlobId(partitionId); assertEquals(blobId.getPartition(), partitionId); System.out.println("Blob Id toString: " + blobId); System.out.println("Blob id sizeInBytes: " + blobId.toString().length()); } /** * Test the parsing of a valid blob ID from a string and stream. * @throws Exception */ @Test public void goodIdTest() throws Exception { MockClusterMap clusterMap = new MockClusterMap(); short goodVersion = 1; PartitionId goodPartitionId = clusterMap.getWritablePartitionIds().get(0); String goodUUID = UUID.randomUUID().toString(); String goodId = buildBlobIdLike(goodVersion, goodPartitionId, goodUUID.length(), goodUUID); List<BlobId> blobIds = new ArrayList<>(); blobIds.add(new BlobId(goodId, clusterMap)); blobIds.add(new BlobId(getStreamFromBase64(goodId), clusterMap)); blobIds.add(new BlobId(getStreamFromBase64(goodId + "EXTRA"), clusterMap)); for (BlobId blobId : blobIds) { assertEquals("Wrong partition ID in blob ID: " + blobId, goodPartitionId, blobId.getPartition()); assertEquals("Wrong base-64 ID in blob ID: " + blobId, goodId, blobId.getID()); } } /** * Test various invalid blob IDs * @throws Exception */ @Test public void badIdTest() throws Exception { MockClusterMap clusterMap = new MockClusterMap(); List<String> blobIdLikes = new ArrayList<>(); short goodVersion = 1; PartitionId goodPartitionId = clusterMap.getWritablePartitionIds().get(0); PartitionId badPartitionId = new MockPartitionId(200000, Collections.EMPTY_LIST, 0); String goodUUID = UUID.randomUUID().toString(); // Partition ID not in cluster map blobIdLikes.add(buildBlobIdLike(goodVersion, badPartitionId, goodUUID.length(), goodUUID)); // UUID length too long blobIdLikes.add(buildBlobIdLike(goodVersion, goodPartitionId, goodUUID.length() + 1, goodUUID)); // UUID length too short blobIdLikes.add(buildBlobIdLike(goodVersion, goodPartitionId, goodUUID.length() - 1, goodUUID)); // UUID length is negative blobIdLikes.add(buildBlobIdLike(goodVersion, goodPartitionId, -1, goodUUID)); // Extra characters after UUID blobIdLikes.add(buildBlobIdLike(goodVersion, goodPartitionId, goodUUID.length(), goodUUID + "EXTRA")); // Invalid version number blobIdLikes.add(buildBlobIdLike((short) (goodVersion + 1), goodPartitionId, goodUUID.length(), goodUUID)); // Empty blob ID blobIdLikes.add(""); // short Blob ID blobIdLikes.add("AA"); for (String blobIdLike : blobIdLikes) { try { new BlobId(blobIdLike, clusterMap); fail("Expected blob ID creation to fail with blob ID string " + blobIdLike); } catch (Exception e) { } } } /** * Build a string that resembles a blob ID, but with possibly invalid sections. * @param version the version number to use in the blob ID * @param partitionId the partition ID to use in the blob ID * @param uuidLength the UUID length to use in the blob ID * @param uuidLike the UUID to use in the blob ID * @return a base-64 encoded {@link String} representing the blob ID */ private String buildBlobIdLike(short version, PartitionId partitionId, int uuidLength, String uuidLike) { final int idLength = 2 + partitionId.getBytes().length + 4 + uuidLike.length(); ByteBuffer idBuf = ByteBuffer.allocate(idLength); idBuf.putShort(version); idBuf.put(partitionId.getBytes()); idBuf.putInt(uuidLength); idBuf.put(uuidLike.getBytes()); return Base64.encodeBase64URLSafeString(idBuf.array()); } /** * Convert a base-64 encoded string into a {@link DataInputStream} * @param base64String the base-64 encoded {@link String} * @return the {@link DataInputStream} */ private DataInputStream getStreamFromBase64(String base64String) { return new DataInputStream(new ByteBufferInputStream(ByteBuffer.wrap(Base64.decodeBase64(base64String)))); } }