@Test
  public void testUpdateRecordV3() throws IOException, MessageFormatException {
    // Test update V3 record
    short accountId = Utils.getRandomShort(TestUtils.RANDOM);
    short containerId = Utils.getRandomShort(TestUtils.RANDOM);
    long updateTimeMs = SystemTime.getInstance().milliseconds() + TestUtils.RANDOM.nextInt();
    long updatedExpiryTimesMs = SystemTime.getInstance().milliseconds() + TestUtils.RANDOM.nextInt();
    for (SubRecord.Type type : SubRecord.Type.values()) {
      ByteBuffer updateRecordBuf = ByteBuffer.allocate(Update_Format_V3.getRecordSize(type));
      UpdateRecord updateRecord = null;
      switch (type) {
        case DELETE:
          DeleteSubRecord deleteSubRecord = new DeleteSubRecord();
          updateRecord = new UpdateRecord(accountId, containerId, updateTimeMs, deleteSubRecord);
          break;
        case TTL_UPDATE:
          TtlUpdateSubRecord ttlUpdateSubRecord = new TtlUpdateSubRecord(updatedExpiryTimesMs);
          updateRecord = new UpdateRecord(accountId, containerId, updateTimeMs, ttlUpdateSubRecord);
          break;
        case UNDELETE:
          UndeleteSubRecord undeleteSubRecord = new UndeleteSubRecord();
          updateRecord = new UpdateRecord(accountId, containerId, updateTimeMs, undeleteSubRecord);
          break;
        default:
          fail("Unknown update record type: " + type);
      }
      Update_Format_V3.serialize(updateRecordBuf, updateRecord);
      updateRecordBuf.flip();
      UpdateRecord deserializeUpdateRecord =
          MessageFormatRecord.deserializeUpdateRecord(new ByteBufferInputStream(updateRecordBuf));
      Assert.assertEquals("AccountId mismatch ", accountId, deserializeUpdateRecord.getAccountId());
      Assert.assertEquals("ContainerId mismatch ", containerId, deserializeUpdateRecord.getContainerId());
      Assert.assertEquals("UpdateTime mismatch ", updateTimeMs, deserializeUpdateRecord.getUpdateTimeInMs());
      Assert.assertEquals("Type of update record incorrect", type, deserializeUpdateRecord.getType());
      switch (type) {
        case DELETE:
          Assert.assertNotNull("DeleteSubRecord is null", deserializeUpdateRecord.getDeleteSubRecord());
          break;
        case TTL_UPDATE:
          TtlUpdateSubRecord ttlUpdateSubRecord = deserializeUpdateRecord.getTtlUpdateSubRecord();
          Assert.assertNotNull("TtlUpdateSubRecord is null", ttlUpdateSubRecord);
          Assert.assertEquals("Updated expiry time is incorrect", updatedExpiryTimesMs,
              ttlUpdateSubRecord.getUpdatedExpiryTimeMs());
          break;
        case UNDELETE:
          Assert.assertNotNull("UndeleteSubRecord is null", deserializeUpdateRecord.getUndeleteSubRecord());
          break;
        default:
          fail("Unknown update record type: " + type);
      }

      // corrupt update V3 record
      updateRecordBuf.flip();
      byte toCorrupt = updateRecordBuf.get(10);
      updateRecordBuf.put(10, (byte) (toCorrupt + 1));
      try {
        MessageFormatRecord.deserializeUpdateRecord(new ByteBufferInputStream(updateRecordBuf));
        fail("Deserialization of a corrupt update record V3 should have failed ");
      } catch (MessageFormatException e) {
        Assert.assertEquals(e.getErrorCode(), MessageFormatErrorCodes.DataCorrupt);
      }
    }
  }
Tests UpdateRecord V3 for serialization and deserialization
@throws IOException
@throws MessageFormatException
ambry-messageformat/src/test/java/com/github/ambry/messageformat/MessageFormatRecordTest.java