Class SlotLeaseStoreContract

java.lang.Object
me.ahoo.cosid.store.tck.SlotLeaseStoreContract

public abstract class SlotLeaseStoreContract extends Object
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 Details

    • TOLERANCE

      protected static final Duration TOLERANCE
      The tolerance of every namespace of the contract (D20 default).
    • LONG_TTL

      protected static final Duration 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

      protected Duration 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

      protected Optional<ManualClock> 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

      protected Duration 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

      protected Duration maxStoreClockOffset()
      How far the store clock may be from the clock of the test machine, for the plausibility check of storeNowComesFromTheStore() on a store without a controllable clock.
      Returns:
      the bound, 5 minutes by default
    • concurrentClients

      protected int concurrentClients()
      How many clients concurrentAcquiresGetDistinctSlots() runs at once; it uses clients * 2 / 3 slots, 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.