@Test
  public void forceDeleteTest() throws IOException, InterruptedException, GeneralSecurityException {
    MockClusterMap clusterMap = http2Cluster.getClusterMap();
    DataNodeId dataNodeId = http2Cluster.getGeneralDataNode();
    SSLFactory sslFactory = new NettySslHttp2Factory(clientSSLConfig);
    Http2NetworkClient networkClient = new Http2NetworkClient(new Http2ClientMetrics(new MetricRegistry()),
        new Http2ClientConfig(new VerifiableProperties(new Properties())), sslFactory, eventLoopGroup);
    BlobProperties properties = new BlobProperties(1024, "serviceid1", Utils.getRandomShort(TestUtils.RANDOM),
        Utils.getRandomShort(TestUtils.RANDOM), false);
    List<? extends PartitionId> partitionIds =
        clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS);
    short blobIdVersion = CommonTestUtils.getCurrentBlobIdVersion();
    BlobId blobId = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(),
        properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false,
        BlobId.BlobDataType.DATACHUNK);

    // Delete a non-existent blob without enabling force delete. We should receive blob_not_found error
    DeleteRequest deleteRequest =
        new DeleteRequest(2, "http2-clientid", blobId, SystemTime.getInstance().milliseconds());
    RequestInfo request =
        new RequestInfo(dataNodeId.getHostname(), new Port(dataNodeId.getHttp2Port(), PortType.HTTP2), deleteRequest,
            clusterMap.getReplicaIds(dataNodeId).get(0), null);
    List<ResponseInfo> responseInfos =
        networkClient.sendAndPoll(Collections.singletonList(request), new HashSet<>(), 300);
    long startTime = SystemTime.getInstance().milliseconds();
    while (responseInfos.size() == 0) {
      responseInfos = networkClient.sendAndPoll(Collections.EMPTY_LIST, new HashSet<>(), 300);
      if (SystemTime.getInstance().milliseconds() - startTime >= 3000) {
        fail("Network Client no response and timeout.");
      }
      Thread.sleep(30);
    }
    NettyByteBufDataInputStream dis = new NettyByteBufDataInputStream(responseInfos.get(0).content());
    DeleteResponse deleteResponse = DeleteResponse.readFrom(dis);
    assertEquals("Should receive blob_not_found error", ServerErrorCode.BlobNotFound, deleteResponse.getError());
    responseInfos.get(0).release();

    // Delete a non-existent blob with enabling force delete. We should not receive any error
    // Enable force delete by setting 'isForceDelete' flag to true
    deleteRequest =
        new DeleteRequest(2, "http2-clientid", blobId, SystemTime.getInstance().milliseconds(), (short) 3, true);
    request =
        new RequestInfo(dataNodeId.getHostname(), new Port(dataNodeId.getHttp2Port(), PortType.HTTP2), deleteRequest,
            clusterMap.getReplicaIds(dataNodeId).get(0), null);
    responseInfos = networkClient.sendAndPoll(Collections.singletonList(request), new HashSet<>(), 300);
    startTime = SystemTime.getInstance().milliseconds();
    while (responseInfos.size() == 0) {
      responseInfos = networkClient.sendAndPoll(Collections.EMPTY_LIST, new HashSet<>(), 300);
      if (SystemTime.getInstance().milliseconds() - startTime >= 3000) {
        fail("Network Client no response and timeout.");
      }
      Thread.sleep(30);
    }
    dis = new NettyByteBufDataInputStream(responseInfos.get(0).content());
    deleteResponse = DeleteResponse.readFrom(dis);
    assertEquals("Should not receive any error", ServerErrorCode.NoError, deleteResponse.getError());
    responseInfos.get(0).release();
  }
Tests writing delete tombstone to server when blob is missing
ambry-server/src/integration-test/java/com/github/ambry/server/Http2NetworkClientTest.java