public Supplier<Stream<TestOperation>> makeOpsAtRandomOffsets(
            OffsetGeneratorParameters offsetParams,
            String description,
            boolean isMutation,
            ObjObjIntIntConsumer<TestState, Entry<Item>> action
        ) {

            return () -> {
                var rnd = new Random(staticRandom.nextInt());
                var indexes = Interval.of(
                    offsetParams.fromInclusive ? offsetParams.indexFrom - 1 : offsetParams.indexFrom,
                    offsetParams.toInclusive ? offsetParams.indexTo : offsetParams.indexTo + 1
                );
                return IntStream.range(0, offsetParams.amount).mapToObj(n -> this.makeOperation(description, isMutation, s -> {
                    int entryIndex = rnd.nextInt(indexes.a, indexes.b);
                    var entries = s.arrayBacked.toListOfEntries();
                    // TODO consider limits
                    var entry = entryIndex >= 0 && entryIndex < entries.size() ? entries.get(entryIndex) : null;
                    var nextEntry = entryIndex + 1 >= 0 && entryIndex + 1 < entries.size() ? entries.get(entryIndex + 1) : null;

                    int offsetFrom, offsetTo;
                    if (entry == null) {
                        if (nextEntry == null) {
                            offsetFrom = entries.get(entries.size() - 1).offset;
                            offsetTo = Integer.MAX_VALUE / 2;
                        } else {
                            offsetFrom = 0;
                            offsetTo = nextEntry.offset;
                        }
                    } else {
                        offsetFrom = offsetParams.excludeExact ? entry.offset + 1 : entry.offset;
                        if (nextEntry == null) {
                            offsetTo = entry.offset + offsetParams.deltaLimit;
                        } else {
                            offsetTo = nextEntry.offset;
                        }
                    }

                    int offset = rnd.nextInt(offsetFrom, offsetTo);
                    action.accept(s, entry != null && entry.offset == offset ? entry : null, offset, entryIndex);
                }));
            };
        }
Test scenarios to cover OffsetKeyedTreeMap data structure

orderings (M)
 - ascending
 - descending
 - random
<p>
modification scenarios (P)
 - all insertions (n)
 - all insertions, then all remove (different series proportions n,m)
 - intermixed insertions and remove (different series proportions n,m)
 - all insertions, then apply offset at existing key
 - all insertions, then apply offset at missing key
 - intermixed insertions, remove, apply offset (different series proportions n,m,p)
 - all insertions, then removeAtRange at existing key
 - all insertions, then removeAtRange offset at missing key
 - intermixed insertions, removeAtRange, apply offset (different series proportions n,m,p)
<p>
inspection scenarios (Q)
 - find existing key
 - find missing key
 - find existing key and iterate forward/backward till the end/head
 - find missing key and iterate forward/backward till the end/head
 - random backward-forward iterations
<p>
test/org.jkiss.dbeaver.model.lsm.test/src/org/jkiss/dbeaver/model/lsm/test/OffsetKeyedTreeMapTest.java