fix ListIterator backwards iteration within moved ranges

This commit is contained in:
Kevin Jahns 2022-03-29 16:55:22 +02:00
parent c4b28aceec
commit f65d1b8475
3 changed files with 36 additions and 23 deletions

View File

@ -185,7 +185,7 @@ export class ContentMove {
if (!start.deleted) { if (!start.deleted) {
const currMoved = start.moved const currMoved = start.moved
const nextPrio = currMoved ? /** @type {ContentMove} */ (currMoved.content).priority : -1 const nextPrio = currMoved ? /** @type {ContentMove} */ (currMoved.content).priority : -1
if (currMoved === null || adaptPriority || nextPrio < this.priority || currMoved.id.client < item.id.client || (currMoved.id.client === item.id.client && currMoved.id.clock < item.id.clock)) { if (adaptPriority || nextPrio < this.priority || (currMoved != null && nextPrio === this.priority && (currMoved.id.client < item.id.client || (currMoved.id.client === item.id.client && currMoved.id.clock < item.id.clock)))) {
if (currMoved !== null) { if (currMoved !== null) {
this.overrides.add(currMoved) this.overrides.add(currMoved)
} }
@ -198,7 +198,7 @@ export class ContentMove {
transaction.prevMoved.set(start, prevMove) transaction.prevMoved.set(start, prevMove)
} }
start.moved = item start.moved = item
} else { } else if (currMoved != null) {
/** @type {ContentMove} */ (currMoved.content).overrides.add(item) /** @type {ContentMove} */ (currMoved.content).overrides.add(item)
} }
} }

View File

@ -118,6 +118,7 @@ export class ListIterator {
} }
let item = this.nextItem let item = this.nextItem
this.index += len this.index += len
// @todo this condition is not needed, better to remove it (can always be applied)
if (this.rel) { if (this.rel) {
len += this.rel len += this.rel
this.rel = 0 this.rel = 0
@ -197,11 +198,9 @@ export class ListIterator {
this.rel -= len this.rel -= len
return this return this
} }
let item = this.nextItem && this.nextItem.left let item = this.nextItem
if (this.rel) { len += ((item && item.countable && !item.deleted && item.moved === this.currMove) ? item.length : 0) - this.rel
len -= this.rel this.rel = 0
this.rel = 0
}
while (item && len > 0) { while (item && len > 0) {
if (item.countable && !item.deleted && item.moved === this.currMove) { if (item.countable && !item.deleted && item.moved === this.currMove) {
len -= item.length len -= item.length

View File

@ -540,6 +540,20 @@ const getUniqueNumber = () => _uniqueNumber++
* @todo to replace content to a separate data structure so we know that insert & returns work as expected!!! * @todo to replace content to a separate data structure so we know that insert & returns work as expected!!!
*/ */
const arrayTransactions = [ const arrayTransactions = [
function move (user, gen) {
const yarray = user.getArray('array')
if (yarray.length === 0) {
return
}
const pos = prng.int32(gen, 0, yarray.length - 1)
const newPos = prng.int32(gen, 0, yarray.length)
const oldContent = yarray.toArray()
yarray.move(pos, newPos)
const [x] = oldContent.splice(pos, 1)
oldContent.splice(pos < newPos ? newPos - 1 : newPos, 0, x)
t.compareArrays(yarray.toArray(), oldContent) // we want to make sure that fastSearch markers insert at the correct position
},
// @todo remove this duplicate!!
function move (user, gen) { function move (user, gen) {
const yarray = user.getArray('array') const yarray = user.getArray('array')
if (yarray.length === 0) { if (yarray.length === 0) {
@ -654,91 +668,91 @@ const compareTestobjects = cmp => {
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests6 = tc => { export const testRepeatGeneratingYarrayTests6 = tc => {
compareTestobjects(applyRandomTests(tc, arrayTransactions, 7, monitorArrayTestObject)) compareTestobjects(applyRandomTests(tc, arrayTransactions, 9, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests40 = tc => { export const testRepeatGeneratingYarrayTests40 = tc => {
applyRandomTests(tc, arrayTransactions, 40) compareTestobjects(applyRandomTests(tc, arrayTransactions, 40, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests42 = tc => { export const testRepeatGeneratingYarrayTests42 = tc => {
applyRandomTests(tc, arrayTransactions, 42) compareTestobjects(applyRandomTests(tc, arrayTransactions, 42, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests43 = tc => { export const testRepeatGeneratingYarrayTests43 = tc => {
applyRandomTests(tc, arrayTransactions, 43) compareTestobjects(applyRandomTests(tc, arrayTransactions, 43, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests44 = tc => { export const testRepeatGeneratingYarrayTests44 = tc => {
applyRandomTests(tc, arrayTransactions, 44) compareTestobjects(applyRandomTests(tc, arrayTransactions, 44, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests45 = tc => { export const testRepeatGeneratingYarrayTests45 = tc => {
applyRandomTests(tc, arrayTransactions, 45) compareTestobjects(applyRandomTests(tc, arrayTransactions, 45, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests46 = tc => { export const testRepeatGeneratingYarrayTests46 = tc => {
applyRandomTests(tc, arrayTransactions, 46) compareTestobjects(applyRandomTests(tc, arrayTransactions, 46, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests300 = tc => { export const testRepeatGeneratingYarrayTests300 = tc => {
applyRandomTests(tc, arrayTransactions, 300) compareTestobjects(applyRandomTests(tc, arrayTransactions, 300, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests400 = tc => { export const testRepeatGeneratingYarrayTests400 = tc => {
applyRandomTests(tc, arrayTransactions, 400) compareTestobjects(applyRandomTests(tc, arrayTransactions, 400, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests500 = tc => { export const testRepeatGeneratingYarrayTests500 = tc => {
applyRandomTests(tc, arrayTransactions, 500) compareTestobjects(applyRandomTests(tc, arrayTransactions, 500, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests600 = tc => { export const testRepeatGeneratingYarrayTests600 = tc => {
applyRandomTests(tc, arrayTransactions, 600) compareTestobjects(applyRandomTests(tc, arrayTransactions, 600, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests1000 = tc => { export const testRepeatGeneratingYarrayTests1000 = tc => {
applyRandomTests(tc, arrayTransactions, 1000) compareTestobjects(applyRandomTests(tc, arrayTransactions, 1000, monitorArrayTestObject))
} }
/** /**
* @param {t.TestCase} tc * @param {t.TestCase} tc
*/ */
export const testRepeatGeneratingYarrayTests1800 = tc => { export const testRepeatGeneratingYarrayTests1800 = tc => {
applyRandomTests(tc, arrayTransactions, 1800) compareTestobjects(applyRandomTests(tc, arrayTransactions, 1800, monitorArrayTestObject))
} }
/** /**
@ -746,7 +760,7 @@ export const testRepeatGeneratingYarrayTests1800 = tc => {
*/ */
export const testRepeatGeneratingYarrayTests3000 = tc => { export const testRepeatGeneratingYarrayTests3000 = tc => {
t.skip(!t.production) t.skip(!t.production)
applyRandomTests(tc, arrayTransactions, 3000) compareTestobjects(applyRandomTests(tc, arrayTransactions, 3000, monitorArrayTestObject))
} }
/** /**
@ -754,7 +768,7 @@ export const testRepeatGeneratingYarrayTests3000 = tc => {
*/ */
export const testRepeatGeneratingYarrayTests5000 = tc => { export const testRepeatGeneratingYarrayTests5000 = tc => {
t.skip(!t.production) t.skip(!t.production)
applyRandomTests(tc, arrayTransactions, 5000) compareTestobjects(applyRandomTests(tc, arrayTransactions, 5000, monitorArrayTestObject))
} }
/** /**
@ -762,5 +776,5 @@ export const testRepeatGeneratingYarrayTests5000 = tc => {
*/ */
export const testRepeatGeneratingYarrayTests30000 = tc => { export const testRepeatGeneratingYarrayTests30000 = tc => {
t.skip(!t.production) t.skip(!t.production)
applyRandomTests(tc, arrayTransactions, 30000) compareTestobjects(applyRandomTests(tc, arrayTransactions, 30000, monitorArrayTestObject))
} }