}
@Test
public void testRemoveOldShardFixCorrupted() throws IOException
{
CounterContext ctx = CounterContext.instance();
int now = (int) (System.currentTimeMillis() / 1000);
// Check that corrupted context created prior to #2968 are fixed by removeOldShards
CounterId id1 = CounterId.getLocalId();
CounterId.renewLocalId();
CounterId id2 = CounterId.getLocalId();
ContextState state = ContextState.allocate(3, 2);
state.writeElement(CounterId.fromInt(1), 1, 4, false);
state.writeElement(id1, 3, 2, true);
state.writeElement(id2, -100, 5, true); // corrupted!
assert ctx.total(state.context) == 11;
try
{
ByteBuffer merger = ctx.computeOldShardMerger(state.context, Collections.<CounterId.CounterIdRecord>emptyList(), 0);
ctx.removeOldShards(ctx.merge(state.context, merger, HeapAllocator.instance), now);
fail("RemoveOldShards should throw an exception if the current id is non-sensical");
}
catch (RuntimeException e) {}
CounterId.renewLocalId();
ByteBuffer merger = ctx.computeOldShardMerger(state.context, Collections.<CounterId.CounterIdRecord>emptyList(), 0);
ByteBuffer cleaned = ctx.removeOldShards(ctx.merge(state.context, merger, HeapAllocator.instance), now);
assert ctx.total(cleaned) == 11;
// Check it is not corrupted anymore
ContextState state2 = new ContextState(cleaned);
while (state2.hasRemaining())
{
assert state2.getClock() >= 0 || state2.getCount() == 0;
state2.moveToNext();
}
// Check that if we merge old and clean on another node, we keep the right count
ByteBuffer onRemote = ctx.merge(ctx.clearAllDelta(state.context), ctx.clearAllDelta(cleaned), HeapAllocator.instance);
assert ctx.total(onRemote) == 11;
}