@ -18,10 +18,13 @@ package org.apache.kafka.coordinator.group;
@@ -18,10 +18,13 @@ package org.apache.kafka.coordinator.group;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData ;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatResponseData ;
import org.apache.kafka.common.message.DeleteGroupsResponseData ;
import org.apache.kafka.common.message.OffsetCommitRequestData ;
import org.apache.kafka.common.message.OffsetCommitResponseData ;
import org.apache.kafka.common.protocol.ApiKeys ;
import org.apache.kafka.common.protocol.Errors ;
import org.apache.kafka.common.requests.RequestContext ;
import org.apache.kafka.common.utils.LogContext ;
import org.apache.kafka.coordinator.group.generated.ConsumerGroupCurrentMemberAssignmentKey ;
import org.apache.kafka.coordinator.group.generated.ConsumerGroupCurrentMemberAssignmentValue ;
import org.apache.kafka.coordinator.group.generated.ConsumerGroupMemberMetadataKey ;
@ -42,14 +45,22 @@ import org.apache.kafka.coordinator.group.runtime.CoordinatorResult;
@@ -42,14 +45,22 @@ import org.apache.kafka.coordinator.group.runtime.CoordinatorResult;
import org.apache.kafka.image.MetadataImage ;
import org.apache.kafka.server.common.ApiMessageAndVersion ;
import org.junit.jupiter.api.Test ;
import org.mockito.ArgumentMatchers ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.List ;
import static org.apache.kafka.coordinator.group.TestUtil.requestContext ;
import static org.junit.jupiter.api.Assertions.assertEquals ;
import static org.junit.jupiter.api.Assertions.assertThrows ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.ArgumentMatchers.anyList ;
import static org.mockito.ArgumentMatchers.anyString ;
import static org.mockito.ArgumentMatchers.eq ;
import static org.mockito.Mockito.doAnswer ;
import static org.mockito.Mockito.doThrow ;
import static org.mockito.Mockito.mock ;
import static org.mockito.Mockito.times ;
import static org.mockito.Mockito.verify ;
@ -62,6 +73,7 @@ public class GroupCoordinatorShardTest {
@@ -62,6 +73,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -86,6 +98,7 @@ public class GroupCoordinatorShardTest {
@@ -86,6 +98,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -105,11 +118,127 @@ public class GroupCoordinatorShardTest {
@@ -105,11 +118,127 @@ public class GroupCoordinatorShardTest {
assertEquals ( result , coordinator . commitOffset ( context , request ) ) ;
}
@Test
public void testDeleteGroups ( ) {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
RequestContext context = requestContext ( ApiKeys . DELETE_GROUPS ) ;
List < String > groupIds = Arrays . asList ( "group-id-1" , "group-id-2" ) ;
DeleteGroupsResponseData . DeletableGroupResultCollection expectedResultCollection = new DeleteGroupsResponseData . DeletableGroupResultCollection ( ) ;
List < Record > expectedRecords = new ArrayList < > ( ) ;
for ( String groupId : groupIds ) {
expectedResultCollection . add ( new DeleteGroupsResponseData . DeletableGroupResult ( ) . setGroupId ( groupId ) ) ;
expectedRecords . addAll ( Arrays . asList (
RecordHelpers . newOffsetCommitTombstoneRecord ( groupId , "topic-name" , 0 ) ,
RecordHelpers . newGroupMetadataTombstoneRecord ( groupId )
) ) ;
}
CoordinatorResult < DeleteGroupsResponseData . DeletableGroupResultCollection , Record > expectedResult = new CoordinatorResult < > (
expectedRecords ,
expectedResultCollection
) ;
when ( offsetMetadataManager . deleteAllOffsets ( anyString ( ) , anyList ( ) ) ) . thenAnswer ( invocation - > {
String groupId = invocation . getArgument ( 0 ) ;
List < Record > records = invocation . getArgument ( 1 ) ;
records . add ( RecordHelpers . newOffsetCommitTombstoneRecord ( groupId , "topic-name" , 0 ) ) ;
return 1 ;
} ) ;
// Mockito#when only stubs method returning non-void value, so we use Mockito#doAnswer instead.
doAnswer ( invocation - > {
String groupId = invocation . getArgument ( 0 ) ;
List < Record > records = invocation . getArgument ( 1 ) ;
records . add ( RecordHelpers . newGroupMetadataTombstoneRecord ( groupId ) ) ;
return null ;
} ) . when ( groupMetadataManager ) . deleteGroup ( anyString ( ) , anyList ( ) ) ;
CoordinatorResult < DeleteGroupsResponseData . DeletableGroupResultCollection , Record > coordinatorResult =
coordinator . deleteGroups ( context , groupIds ) ;
for ( String groupId : groupIds ) {
verify ( groupMetadataManager , times ( 1 ) ) . validateDeleteGroup ( ArgumentMatchers . eq ( groupId ) ) ;
verify ( groupMetadataManager , times ( 1 ) ) . deleteGroup ( ArgumentMatchers . eq ( groupId ) , anyList ( ) ) ;
verify ( offsetMetadataManager , times ( 1 ) ) . deleteAllOffsets ( ArgumentMatchers . eq ( groupId ) , anyList ( ) ) ;
}
assertEquals ( expectedResult , coordinatorResult ) ;
}
@Test
public void testDeleteGroupsInvalidGroupId ( ) {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
RequestContext context = requestContext ( ApiKeys . DELETE_GROUPS ) ;
List < String > groupIds = Arrays . asList ( "group-id-1" , "group-id-2" , "group-id-3" ) ;
DeleteGroupsResponseData . DeletableGroupResultCollection expectedResultCollection =
new DeleteGroupsResponseData . DeletableGroupResultCollection ( Arrays . asList (
new DeleteGroupsResponseData . DeletableGroupResult ( )
. setGroupId ( "group-id-1" ) ,
new DeleteGroupsResponseData . DeletableGroupResult ( )
. setGroupId ( "group-id-2" )
. setErrorCode ( Errors . INVALID_GROUP_ID . code ( ) ) ,
new DeleteGroupsResponseData . DeletableGroupResult ( )
. setGroupId ( "group-id-3" )
) . iterator ( ) ) ;
List < Record > expectedRecords = Arrays . asList (
RecordHelpers . newOffsetCommitTombstoneRecord ( "group-id-1" , "topic-name" , 0 ) ,
RecordHelpers . newGroupMetadataTombstoneRecord ( "group-id-1" ) ,
RecordHelpers . newOffsetCommitTombstoneRecord ( "group-id-3" , "topic-name" , 0 ) ,
RecordHelpers . newGroupMetadataTombstoneRecord ( "group-id-3" )
) ;
CoordinatorResult < DeleteGroupsResponseData . DeletableGroupResultCollection , Record > expectedResult = new CoordinatorResult < > (
expectedRecords ,
expectedResultCollection
) ;
// Mockito#when only stubs method returning non-void value, so we use Mockito#doAnswer and Mockito#doThrow instead.
doThrow ( Errors . INVALID_GROUP_ID . exception ( ) )
. when ( groupMetadataManager ) . validateDeleteGroup ( ArgumentMatchers . eq ( "group-id-2" ) ) ;
doAnswer ( invocation - > {
String groupId = invocation . getArgument ( 0 ) ;
List < Record > records = invocation . getArgument ( 1 ) ;
records . add ( RecordHelpers . newOffsetCommitTombstoneRecord ( groupId , "topic-name" , 0 ) ) ;
return null ;
} ) . when ( offsetMetadataManager ) . deleteAllOffsets ( anyString ( ) , anyList ( ) ) ;
doAnswer ( invocation - > {
String groupId = invocation . getArgument ( 0 ) ;
List < Record > records = invocation . getArgument ( 1 ) ;
records . add ( RecordHelpers . newGroupMetadataTombstoneRecord ( groupId ) ) ;
return null ;
} ) . when ( groupMetadataManager ) . deleteGroup ( anyString ( ) , anyList ( ) ) ;
CoordinatorResult < DeleteGroupsResponseData . DeletableGroupResultCollection , Record > coordinatorResult =
coordinator . deleteGroups ( context , groupIds ) ;
for ( String groupId : groupIds ) {
verify ( groupMetadataManager , times ( 1 ) ) . validateDeleteGroup ( eq ( groupId ) ) ;
if ( ! groupId . equals ( "group-id-2" ) ) {
verify ( groupMetadataManager , times ( 1 ) ) . deleteGroup ( eq ( groupId ) , anyList ( ) ) ;
verify ( offsetMetadataManager , times ( 1 ) ) . deleteAllOffsets ( eq ( groupId ) , anyList ( ) ) ;
}
}
assertEquals ( expectedResult , coordinatorResult ) ;
}
@Test
public void testReplayOffsetCommit ( ) {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -135,6 +264,7 @@ public class GroupCoordinatorShardTest {
@@ -135,6 +264,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -159,6 +289,7 @@ public class GroupCoordinatorShardTest {
@@ -159,6 +289,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -179,6 +310,7 @@ public class GroupCoordinatorShardTest {
@@ -179,6 +310,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -198,6 +330,7 @@ public class GroupCoordinatorShardTest {
@@ -198,6 +330,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -218,6 +351,7 @@ public class GroupCoordinatorShardTest {
@@ -218,6 +351,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -237,6 +371,7 @@ public class GroupCoordinatorShardTest {
@@ -237,6 +371,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -257,6 +392,7 @@ public class GroupCoordinatorShardTest {
@@ -257,6 +392,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -276,6 +412,7 @@ public class GroupCoordinatorShardTest {
@@ -276,6 +412,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -296,6 +433,7 @@ public class GroupCoordinatorShardTest {
@@ -296,6 +433,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -315,6 +453,7 @@ public class GroupCoordinatorShardTest {
@@ -315,6 +453,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -335,6 +474,7 @@ public class GroupCoordinatorShardTest {
@@ -335,6 +474,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -354,6 +494,7 @@ public class GroupCoordinatorShardTest {
@@ -354,6 +494,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -374,6 +515,7 @@ public class GroupCoordinatorShardTest {
@@ -374,6 +515,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -393,6 +535,7 @@ public class GroupCoordinatorShardTest {
@@ -393,6 +535,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -405,6 +548,7 @@ public class GroupCoordinatorShardTest {
@@ -405,6 +548,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -424,6 +568,7 @@ public class GroupCoordinatorShardTest {
@@ -424,6 +568,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -443,6 +588,7 @@ public class GroupCoordinatorShardTest {
@@ -443,6 +588,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;
@ -463,6 +609,7 @@ public class GroupCoordinatorShardTest {
@@ -463,6 +609,7 @@ public class GroupCoordinatorShardTest {
GroupMetadataManager groupMetadataManager = mock ( GroupMetadataManager . class ) ;
OffsetMetadataManager offsetMetadataManager = mock ( OffsetMetadataManager . class ) ;
GroupCoordinatorShard coordinator = new GroupCoordinatorShard (
new LogContext ( ) ,
groupMetadataManager ,
offsetMetadataManager
) ;