@Test
  public void basicTest() throws IOException {
    int blobSize = 100;
    String serviceId = "ServiceId";
    String ownerId = "OwnerId";
    String contentType = "ContentType";
    String externalAssetTag = "some-external-asset-tag";
    String contentEncoding = version >= BlobPropertiesSerDe.VERSION_4 ? "gzip" : null;
    String filename = version >= BlobPropertiesSerDe.VERSION_4 ? "filename" : null;
    int timeToLiveInSeconds = 144;
    short accountId = Utils.getRandomShort(TestUtils.RANDOM);
    short containerId = Utils.getRandomShort(TestUtils.RANDOM);
    boolean isEncrypted = TestUtils.RANDOM.nextBoolean();

    short accountIdToExpect = version == BlobPropertiesSerDe.VERSION_1 ? UNKNOWN_ACCOUNT_ID : accountId;
    short containerIdToExpect = version == BlobPropertiesSerDe.VERSION_1 ? UNKNOWN_CONTAINER_ID : containerId;
    boolean encryptFlagToExpect = version >= BlobPropertiesSerDe.VERSION_3 && isEncrypted;
    String contentEncodingToExpect = contentEncoding;
    String filenameToExpect = filename;
    String blobId = new BlobId(BlobId.BLOB_ID_V6, BlobId.BlobIdType.NATIVE, (byte) 1, accountId, containerId,
        new MockPartitionId(), false, BlobId.BlobDataType.METADATA).getID();

    BlobProperties blobProperties = new BlobProperties(blobSize, serviceId, null, null, false, Utils.Infinite_Time,
        SystemTime.getInstance().milliseconds(), accountId, containerId, isEncrypted, externalAssetTag, null, null, null);
    System.out.println(blobProperties.toString()); // Provide example of BlobProperties.toString()
    ByteBuffer serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, "", "", false, Utils.Infinite_Time, accountIdToExpect,
        containerIdToExpect, encryptFlagToExpect, null, null, null, null);

    blobProperties = new BlobProperties(blobSize, serviceId, null, null, false, Utils.Infinite_Time,
        SystemTime.getInstance().milliseconds(), accountId, containerId, isEncrypted, externalAssetTag, contentEncoding,
        filename, null);
    System.out.println(blobProperties.toString()); // Provide example of BlobProperties.toString()
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, "", "", false, Utils.Infinite_Time, accountIdToExpect,
        containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);
    assertTrue(blobProperties.getCreationTimeInMs() > 0);
    assertTrue(blobProperties.getCreationTimeInMs() <= System.currentTimeMillis());

    blobProperties = new BlobProperties(blobSize, serviceId, null, null, false, Utils.Infinite_Time,
        SystemTime.getInstance().milliseconds(), accountId, containerId, isEncrypted, externalAssetTag, contentEncoding,
        filename, null);
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, "", "", false, Utils.Infinite_Time, accountIdToExpect,
        containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);

    blobProperties =
        new BlobProperties(blobSize, serviceId, ownerId, contentType, true, timeToLiveInSeconds, accountId, containerId,
            isEncrypted, externalAssetTag, contentEncoding, filename);
    System.out.println(blobProperties.toString()); // Provide example of BlobProperties.toString()

    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, ownerId, contentType, true, timeToLiveInSeconds,
        accountIdToExpect, containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);
    assertTrue(blobProperties.getCreationTimeInMs() > 0);
    assertTrue(blobProperties.getCreationTimeInMs() <= System.currentTimeMillis());

    long creationTimeMs = SystemTime.getInstance().milliseconds();
    blobProperties =
        new BlobProperties(blobSize, serviceId, ownerId, contentType, true, timeToLiveInSeconds, creationTimeMs,
            accountId, containerId, isEncrypted, "some-external-asset-tag", contentEncoding, filename, null);
    System.out.println(blobProperties.toString()); // Provide example of BlobProperties.toString()
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);

    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, ownerId, contentType, true, timeToLiveInSeconds,
        accountIdToExpect, containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);
    assertEquals(blobProperties.getCreationTimeInMs(), creationTimeMs);

    long creationTimeInSecs = TimeUnit.MILLISECONDS.toSeconds(creationTimeMs);
    // valid TTLs
    long[] validTTLs =
        new long[]{TimeUnit.HOURS.toSeconds(1), TimeUnit.HOURS.toSeconds(10), TimeUnit.HOURS.toSeconds(100),
            TimeUnit.DAYS.toSeconds(1), TimeUnit.DAYS.toSeconds(10), TimeUnit.DAYS.toSeconds(100),
            TimeUnit.DAYS.toSeconds(30 * 12), TimeUnit.DAYS.toSeconds(30 * 12 * 10),
            Integer.MAX_VALUE - creationTimeInSecs - 1, Integer.MAX_VALUE - creationTimeInSecs,
            Integer.MAX_VALUE - creationTimeInSecs + 1, Integer.MAX_VALUE - creationTimeInSecs + 100,
            Integer.MAX_VALUE - creationTimeInSecs + 10000};
    for (long ttl : validTTLs) {
      blobProperties =
          new BlobProperties(blobSize, serviceId, ownerId, contentType, true, ttl, creationTimeMs, accountId,
              containerId, isEncrypted, null, contentEncoding, filename, null);
      serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
      blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
          new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
      verifyBlobProperties(blobProperties, blobSize, serviceId, ownerId, contentType, true, ttl, accountIdToExpect,
          containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);
    }

    blobProperties =
        new BlobProperties(blobSize, serviceId, null, null, false, timeToLiveInSeconds, creationTimeMs, accountId,
            containerId, isEncrypted, externalAssetTag, contentEncoding, filename, null);
    verifyBlobProperties(blobProperties, blobSize, serviceId, null, null, false, timeToLiveInSeconds, accountId,
        containerId, isEncrypted, externalAssetTag, contentEncodingToExpect, filenameToExpect, null);
    blobProperties.setTimeToLiveInSeconds(timeToLiveInSeconds + 1);
    verifyBlobProperties(blobProperties, blobSize, serviceId, null, null, false, timeToLiveInSeconds + 1, accountId,
        containerId, isEncrypted, externalAssetTag, contentEncodingToExpect, filenameToExpect, null);
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, "", "", false, timeToLiveInSeconds + 1, accountIdToExpect,
        containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);

    blobProperties.setBlobSize(blobSize + 1);
    verifyBlobProperties(blobProperties, blobSize + 1, serviceId, "", "", false, timeToLiveInSeconds + 1,
        accountIdToExpect, containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize + 1, serviceId, "", "", false, timeToLiveInSeconds + 1,
        accountIdToExpect, containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, null);

    blobProperties =
        new BlobProperties(blobSize, serviceId, null, null, false, timeToLiveInSeconds,
            creationTimeMs, accountId, containerId, isEncrypted, externalAssetTag, contentEncoding, filename, blobId);
    verifyBlobProperties(blobProperties, blobSize, serviceId, null, null, false, timeToLiveInSeconds, accountId,
        containerId, isEncrypted, externalAssetTag, contentEncodingToExpect, filenameToExpect, blobId);
    blobProperties.setTimeToLiveInSeconds(timeToLiveInSeconds + 1);
    verifyBlobProperties(blobProperties, blobSize, serviceId, null, null, false, timeToLiveInSeconds + 1, accountId,
        containerId, isEncrypted, externalAssetTag, contentEncodingToExpect, filenameToExpect, blobId);
    serializedBuffer = serializeBlobPropertiesInVersion(blobProperties);
    blobProperties = BlobPropertiesSerDe.getBlobPropertiesFromStream(
        new DataInputStream(new ByteBufferInputStream(serializedBuffer)));
    verifyBlobProperties(blobProperties, blobSize, serviceId, "", "", false, timeToLiveInSeconds + 1, accountIdToExpect,
        containerIdToExpect, encryptFlagToExpect, null, contentEncodingToExpect, filenameToExpect, version > VERSION_4 ? blobId : null);
  }
Running for {@link BlobPropertiesSerDe#VERSION_1} and {@link BlobPropertiesSerDe#VERSION_2}
@return an array with both the versions ({@link BlobPropertiesSerDe#VERSION_1} and {@link BlobPropertiesSerDe#VERSION_2}).
ambry-messageformat/src/test/java/com/github/ambry/messageformat/BlobPropertiesTest.java