Package me.ahoo.cosid.store.tck
Class SlotLeaseStoreContract
java.lang.Object
me.ahoo.cosid.store.tck.SlotLeaseStoreContract
The
SlotLeaseStore contract (05-machine-lease.md §2, 06-stores.md §3). A backend test extends it and
implements newStore(). Every case uses a namespace of its own, so the cases share one backend safely.
The cases never read a client clock. The ones that need a lease to expire acquire it with shortTtl()
and retry the takeover until the store lets it through, so they hold on a loaded machine; a store whose clock the
test controls returns it from storeClock(), and the cases move it instead of waiting.
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidBasics: acquire flags a live lease of the same owner key under another incarnation, and only a live one.voidBasics: acquiring again with the same key and incarnation returns the same slot and fence.voidBasics: with every slot below the limit held, acquire returns Exhausted with the earliest expiry.voidBasics: acquired slots are within [0, limit), for limit 1 and 2^bits.voidBasics: without preferred or sticky slot, the lowest free slot is taken.voidBasics: a free preferred slot is taken before the sticky and the lowest ones.voidBasics: a new incarnation of an owner key gets back the free slot that key held last.voidSafety: over renewals, releases and takeovers, ceiling and the next floor of a slot never go down.voidConcurrency: N clients acquiring in one namespace at once get pairwise distinct slots.protected intHow many clientsconcurrentAcquiresGetDistinctSlots()runs at once; it usesclients * 2 / 3slots, so a third of them find the namespace exhausted.voidSafety: once taken over, renew of the previous holder returns empty and its release returns false.voidClock: expiresAt minus storeNow equals ttl: both come from the same write.voidSafety: after release(lease, lastIssued), the floor of the next holder is at least min(lastIssued, ceiling) and at least the released floor.protected DurationHow far the store clock may be from the clock of the test machine, for the plausibility check ofstoreNowComesFromTheStore()on a store without a controllable clock.protected abstract me.ahoo.cosid.lease.SlotLeaseStorenewStore()A store on the backend under test.voidMetadata: acquiring with another limit or tolerance than the namespace was first used with throws NamespaceMismatchException.voidMetadata: the slot offset is recorded with the limit and the tolerance (api-freeze.md §2.5.1); another offset throws NamespaceMismatchException, and the offset does not change the slots: they stay[0, limit).voidSafety: replaying a renew keeps the fence and succeeds.voidSafety: a live lease is never taken over by the same owner key with another incarnation.protected DurationshortTtl()The ttl of tests that wait for a lease to expire: short, but long enough for the clock resolution of the backend.protected Optional<ManualClock> The store clock, when the test controls it: the expiry cases then move it past the expiry instead of waiting.protected intHow many store instances the concurrency cases spread the clients over.voidClock: storeNow is the store clock, not the client clock.voidKeys: the longest portable namespace and owner key (StoreKeys, R1-spi-02) are stored and read back as they are, every allowed punctuation and a non-ASCII owner key included.voidSafety: after expiry, the floor of the next holder is at least the last ceiling stored for the previous holder.protected DurationHow long a case waits for an expired lease to be taken over before it fails.
-
Field Details
-
TOLERANCE
The tolerance of every namespace of the contract (D20 default). -
LONG_TTL
The ttl of leases that must not expire during a case.
-
-
Constructor Details
-
SlotLeaseStoreContract
public SlotLeaseStoreContract()
-
-
Method Details
-
newStore
protected abstract me.ahoo.cosid.lease.SlotLeaseStore newStore()A store on the backend under test. Each call opens a new instance on the same data, so tests can act as several clients; tests close what they open.- Returns:
- a new store instance
-
shortTtl
The ttl of tests that wait for a lease to expire: short, but long enough for the clock resolution of the backend.- Returns:
- the ttl
-
storeClock
The store clock, when the test controls it: the expiry cases then move it past the expiry instead of waiting. A real backend keeps the default.- Returns:
- the controllable store clock, empty by default
-
takeoverTimeout
How long a case waits for an expired lease to be taken over before it fails.- Returns:
- the wait, by default 20 short ttls plus 10 seconds
-
maxStoreClockOffset
How far the store clock may be from the clock of the test machine, for the plausibility check ofstoreNowComesFromTheStore()on a store without a controllable clock.- Returns:
- the bound, 5 minutes by default
-
concurrentClients
protected int concurrentClients()How many clientsconcurrentAcquiresGetDistinctSlots()runs at once; it usesclients * 2 / 3slots, so a third of them find the namespace exhausted.- Returns:
- the client count, 24 by default
-
storeInstances
protected int storeInstances()How many store instances the concurrency cases spread the clients over.- Returns:
- the instance count, 4 by default
-
acquireIsIdempotentForTheSameOwner
@Test public void acquireIsIdempotentForTheSameOwner()Basics: acquiring again with the same key and incarnation returns the same slot and fence. -
acquireTakesThePreferredSlot
@Test public void acquireTakesThePreferredSlot()Basics: a free preferred slot is taken before the sticky and the lowest ones. -
acquireTakesTheStickySlotOfTheOwnerKey
@Test public void acquireTakesTheStickySlotOfTheOwnerKey()Basics: a new incarnation of an owner key gets back the free slot that key held last. -
acquireTakesTheLowestFreeSlot
@Test public void acquireTakesTheLowestFreeSlot()Basics: without preferred or sticky slot, the lowest free slot is taken. -
acquireFlagsDuplicateOwnerKeys
@Test public void acquireFlagsDuplicateOwnerKeys()Basics: acquire flags a live lease of the same owner key under another incarnation, and only a live one. -
acquireReturnsExhaustedWhenEverySlotIsHeld
@Test public void acquireReturnsExhaustedWhenEverySlotIsHeld()Basics: with every slot below the limit held, acquire returns Exhausted with the earliest expiry. -
acquireStaysBelowTheLimit
@Test public void acquireStaysBelowTheLimit()Basics: acquired slots are within [0, limit), for limit 1 and 2^bits. -
takeoverFloorIsAtLeastThePreviousStoredCeiling
@Test public void takeoverFloorIsAtLeastThePreviousStoredCeiling()Safety: after expiry, the floor of the next holder is at least the last ceiling stored for the previous holder. -
floorAfterReleaseIsAtLeastLastIssued
@Test public void floorAfterReleaseIsAtLeastLastIssued()Safety: after release(lease, lastIssued), the floor of the next holder is at least min(lastIssued, ceiling) and at least the released floor. -
ceilingAndNextFloorNeverDecrease
@Test public void ceilingAndNextFloorNeverDecrease()Safety: over renewals, releases and takeovers, ceiling and the next floor of a slot never go down. -
sameKeyWithAnotherIncarnationNeverTakesOver
@Test public void sameKeyWithAnotherIncarnationNeverTakesOver()Safety: a live lease is never taken over by the same owner key with another incarnation. -
expiredHolderCannotRenewOrRelease
@Test public void expiredHolderCannotRenewOrRelease()Safety: once taken over, renew of the previous holder returns empty and its release returns false. -
renewIsIdempotent
@Test public void renewIsIdempotent()Safety: replaying a renew keeps the fence and succeeds. -
storeNowComesFromTheStore
@Test public void storeNowComesFromTheStore()Clock: storeNow is the store clock, not the client clock. -
expiresAtIsTtlAfterStoreNow
@Test public void expiresAtIsTtlAfterStoreNow()Clock: expiresAt minus storeNow equals ttl: both come from the same write. -
concurrentAcquiresGetDistinctSlots
@Test public void concurrentAcquiresGetDistinctSlots()Concurrency: N clients acquiring in one namespace at once get pairwise distinct slots. -
rejectsMismatchedNamespaceParameters
@Test public void rejectsMismatchedNamespaceParameters()Metadata: acquiring with another limit or tolerance than the namespace was first used with throws NamespaceMismatchException. -
rejectsMismatchedSlotOffset
@Test public void rejectsMismatchedSlotOffset()Metadata: the slot offset is recorded with the limit and the tolerance (api-freeze.md §2.5.1); another offset throws NamespaceMismatchException, and the offset does not change the slots: they stay[0, limit). -
storesTheLongestPortableNamespaceAndOwnerKey
@Test public void storesTheLongestPortableNamespaceAndOwnerKey()Keys: the longest portable namespace and owner key (StoreKeys, R1-spi-02) are stored and read back as they are, every allowed punctuation and a non-ASCII owner key included.
-