/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kafka.clients.producer.internals;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.record.CompressionType;
import org.apache.kafka.common.record.MemoryRecords;
import org.apache.kafka.common.record.MemoryRecordsBuilder;
import org.apache.kafka.common.record.Record;
import org.apache.kafka.common.record.TimestampType;
import org.junit.Test;
import java.nio.ByteBuffer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class ProducerBatchTest {
private final long now = 1488748346917L;
private final MemoryRecordsBuilder memoryRecordsBuilder = MemoryRecords.builder(ByteBuffer.allocate(128),
CompressionType.NONE, TimestampType.CREATE_TIME, 128);
/**
* A {@link ProducerBatch} configured using a very large linger value and a timestamp preceding its create
* time is interpreted correctly as not expired when the linger time is larger than the difference
* between now and create time by {@link ProducerBatch#maybeExpire(int, long, long, long, boolean)}.
*/
@Test
public void testLargeLingerOldNowExpire() {
ProducerBatch batch = new ProducerBatch(new TopicPartition("topic", 1), memoryRecordsBuilder, now);
// Set `now` to 2ms before the create time.
assertFalse(batch.maybeExpire(10240, 100L, now - 2L, Long.MAX_VALUE, false));
}
/**
* A {@link ProducerBatch} configured using a very large retryBackoff value with retry = true and a timestamp
* preceding its create time is interpreted correctly as not expired when the retryBackoff time is larger than the
* difference between now and create time by {@link ProducerBatch#maybeExpire(int, long, long, long, boolean)}.
*/
@Test
public void testLargeRetryBackoffOldNowExpire() {
ProducerBatch batch = new ProducerBatch(new TopicPartition("topic", 1), memoryRecordsBuilder, now);
// Set batch.retry = true
batch.reenqueued(now);
// Set `now` to 2ms before the create time.
assertFalse(batch.maybeExpire(10240, Long.MAX_VALUE, now - 2L, 10240L, false));
}
/**
* A {@link ProducerBatch#maybeExpire(int, long, long, long, boolean)} call with a now value before the create
* time of the ProducerBatch is correctly recognized as not expired when invoked with parameter isFull = true.
*/
@Test
public void testLargeFullOldNowExpire() {
ProducerBatch batch = new ProducerBatch(new TopicPartition("topic", 1), memoryRecordsBuilder, now);
// Set `now` to 2ms before the create time.
assertFalse(batch.maybeExpire(10240, 10240L, now - 2L, 10240L, true));
}
@Test
public void testShouldNotAttemptAppendOnceRecordsBuilderIsClosedForAppends() {
ProducerBatch batch = new ProducerBatch(new TopicPartition("topic", 1), memoryRecordsBuilder, now);
FutureRecordMetadata result0 = batch.tryAppend(now, null, new byte[10], Record.EMPTY_HEADERS, null, now);
assertNotNull(result0);
assertTrue(memoryRecordsBuilder.hasRoomFor(now, null, new byte[10]));
memoryRecordsBuilder.closeForRecordAppends();
assertFalse(memoryRecordsBuilder.hasRoomFor(now, null, new byte[10]));
assertEquals(null, batch.tryAppend(now + 1, null, new byte[10], Record.EMPTY_HEADERS, null, now + 1));
}
}