Program: 8026
Project: 8026
Buggy source:
@Test public void testEvictOnAck_ThreeGroups() throws Exception {
  TTQueue queue=createQueue();
  final boolean singleEntry=true;
  long dirtyVersion=getDirtyWriteVersion();
  ReadPointer dirtyReadPointer=getDirtyPointer();
  QueueConfig config=new QueueConfig(PartitionerType.FIFO,singleEntry);
  QueueConsumer consumer1=new QueueConsumer(0,queue.getGroupID(),1,config);
  QueueConsumer consumer2=new QueueConsumer(0,queue.getGroupID(),1,config);
  QueueConsumer consumer3=new QueueConsumer(0,queue.getGroupID(),1,config);
  int numGroups=3;
  for (int i=0; i < 10; i++) {
    queue.enqueue(new QueueEntry(Bytes.toBytes(i)),dirtyVersion);
  }
  for (int i=0; i < 10; i++) {
    DequeueResult result=queue.dequeue(consumer1,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer1,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer1,numGroups,dirtyReadPointer.getMaximum());
  }
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertFalse(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  for (int i=0; i < 10; i++) {
    DequeueResult result=queue.dequeue(consumer2,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer2,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer2,numGroups,dirtyReadPointer.getMaximum());
  }
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  assertFalse(queue.dequeue(consumer3,dirtyReadPointer).isEmpty());
  for (int i=0; i < 9; i++) {
    DequeueResult result=queue.dequeue(consumer3,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer3,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer3,numGroups,dirtyReadPointer.getMaximum());
  }
  QueueConsumer consumer4=new QueueConsumer(0,queue.getGroupID(),1,config);
  DequeueResult result=queue.dequeue(consumer4,dirtyReadPointer);
  assertTrue("String_Node_Str" + Bytes.toInt(result.getEntry().getData()),Bytes.equals(Bytes.toBytes(9),result.getEntry().getData()));
  queue.ack(result.getEntryPointer(),consumer4,dirtyReadPointer);
  queue.finalize(result.getEntryPointer(),consumer4,++numGroups,dirtyReadPointer.getMaximum());
  assertTrue(queue.dequeue(consumer4,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  result=queue.dequeue(consumer3,dirtyReadPointer);
  assertTrue("String_Node_Str" + Bytes.toInt(result.getEntry().getData()),Bytes.equals(Bytes.toBytes(9),result.getEntry().getData()));
  queue.ack(result.getEntryPointer(),consumer3,dirtyReadPointer);
  queue.finalize(result.getEntryPointer(),consumer3,numGroups,dirtyReadPointer.getMaximum());
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer3,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer4,dirtyReadPointer).isEmpty());
}

Fixed version (ground truth):
@Test public void testEvictOnAck_ThreeGroups() throws Exception {
  TTQueue queue=createQueue();
  final boolean singleEntry=true;
  long dirtyVersion=getDirtyWriteVersion();
  ReadPointer dirtyReadPointer=getDirtyPointer();
  QueueConfig config=new QueueConfig(PartitionerType.FIFO,singleEntry);
  QueueConsumer consumer1=new QueueConsumer(0,2,1,config);
  QueueConsumer consumer2=new QueueConsumer(0,1,1,config);
  QueueConsumer consumer3=new QueueConsumer(0,0,1,config);
  int numGroups=3;
  for (int i=0; i < 10; i++) {
    queue.enqueue(new QueueEntry(Bytes.toBytes(i)),dirtyVersion);
  }
  for (int i=0; i < 10; i++) {
    DequeueResult result=queue.dequeue(consumer1,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer1,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer1,numGroups,dirtyReadPointer.getMaximum());
  }
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertFalse(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  for (int i=0; i < 10; i++) {
    DequeueResult result=queue.dequeue(consumer2,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer2,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer2,numGroups,dirtyReadPointer.getMaximum());
  }
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  assertFalse(queue.dequeue(consumer3,dirtyReadPointer).isEmpty());
  for (int i=0; i < 9; i++) {
    DequeueResult result=queue.dequeue(consumer3,dirtyReadPointer);
    assertTrue(Bytes.equals(Bytes.toBytes(i),result.getEntry().getData()));
    queue.ack(result.getEntryPointer(),consumer3,dirtyReadPointer);
    queue.finalize(result.getEntryPointer(),consumer3,numGroups,dirtyReadPointer.getMaximum());
  }
  QueueConsumer consumer4=new QueueConsumer(0,4,1,config);
  DequeueResult result=queue.dequeue(consumer4,dirtyReadPointer);
  assertFalse(result.isEmpty());
  assertTrue("String_Node_Str" + Bytes.toInt(result.getEntry().getData()),Bytes.equals(Bytes.toBytes(9),result.getEntry().getData()));
  queue.ack(result.getEntryPointer(),consumer4,dirtyReadPointer);
  queue.finalize(result.getEntryPointer(),consumer4,++numGroups,dirtyReadPointer.getMaximum());
  assertTrue(queue.dequeue(consumer4,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  result=queue.dequeue(consumer3,dirtyReadPointer);
  assertTrue("String_Node_Str" + Bytes.toInt(result.getEntry().getData()),Bytes.equals(Bytes.toBytes(9),result.getEntry().getData()));
  queue.ack(result.getEntryPointer(),consumer3,dirtyReadPointer);
  queue.finalize(result.getEntryPointer(),consumer3,numGroups,dirtyReadPointer.getMaximum());
  assertTrue(queue.dequeue(consumer1,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer2,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer3,dirtyReadPointer).isEmpty());
  assertTrue(queue.dequeue(consumer4,dirtyReadPointer).isEmpty());
}