tests: fix memory leaks (#2389)

This commit is contained in:
Mo
2023-08-06 15:23:31 -05:00
committed by GitHub
parent d59e1befff
commit 8655bdb5dd
76 changed files with 3904 additions and 3840 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,37 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable no-undef */
import { BaseItemCounts } from '../lib/BaseItemCounts.js'
import * as Factory from '../lib/factory.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('sync integrity', () => {
before(function () {
localStorage.clear()
})
after(function () {
localStorage.clear()
})
let application
let email
let password
let expectedItemCount
beforeEach(async function () {
this.expectedItemCount = BaseItemCounts.DefaultItemsWithAccount
this.application = await Factory.createInitAppWithFakeCrypto()
this.email = UuidGenerator.GenerateUuid()
this.password = UuidGenerator.GenerateUuid()
localStorage.clear()
expectedItemCount = BaseItemCounts.DefaultItemsWithAccount
application = await Factory.createInitAppWithFakeCrypto()
email = UuidGenerator.GenerateUuid()
password = UuidGenerator.GenerateUuid()
await Factory.registerUserToApplication({
application: this.application,
email: this.email,
password: this.password,
application: application,
email: email,
password: password,
})
})
afterEach(async function () {
expect(application.sync.isOutOfSync()).to.equal(false)
const rawPayloads = await application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(expectedItemCount)
await Factory.safeDeinit(application)
localStorage.clear()
application = undefined
})
const awaitSyncEventPromise = (application, targetEvent) => {
return new Promise((resolve) => {
application.sync.addEventObserver((event) => {
@@ -36,44 +42,37 @@ describe('sync integrity', () => {
})
}
afterEach(async function () {
expect(this.application.sync.isOutOfSync()).to.equal(false)
const rawPayloads = await this.application.storage.getAllRawPayloads()
expect(rawPayloads.length).to.equal(this.expectedItemCount)
await Factory.safeDeinit(this.application)
})
it('should detect when out of sync', async function () {
const item = await this.application.mutator.emitItemFromPayload(
const item = await application.mutator.emitItemFromPayload(
Factory.createNotePayload(),
PayloadEmitSource.LocalChanged,
)
this.expectedItemCount++
expectedItemCount++
const didEnterOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.EnterOutOfSync)
await this.application.sync.sync({ checkIntegrity: true })
const didEnterOutOfSync = awaitSyncEventPromise(application, SyncEvent.EnterOutOfSync)
await application.sync.sync({ checkIntegrity: true })
await this.application.items.removeItemFromMemory(item)
await this.application.sync.sync({ checkIntegrity: true, awaitAll: true })
await application.items.removeItemFromMemory(item)
await application.sync.sync({ checkIntegrity: true, awaitAll: true })
await didEnterOutOfSync
})
it('should self heal after out of sync', async function () {
const item = await this.application.mutator.emitItemFromPayload(
const item = await application.mutator.emitItemFromPayload(
Factory.createNotePayload(),
PayloadEmitSource.LocalChanged,
)
this.expectedItemCount++
expectedItemCount++
const didEnterOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.EnterOutOfSync)
const didExitOutOfSync = awaitSyncEventPromise(this.application, SyncEvent.ExitOutOfSync)
const didEnterOutOfSync = awaitSyncEventPromise(application, SyncEvent.EnterOutOfSync)
const didExitOutOfSync = awaitSyncEventPromise(application, SyncEvent.ExitOutOfSync)
await this.application.sync.sync({ checkIntegrity: true })
await this.application.items.removeItemFromMemory(item)
await this.application.sync.sync({ checkIntegrity: true, awaitAll: true })
await application.sync.sync({ checkIntegrity: true })
await application.items.removeItemFromMemory(item)
await application.sync.sync({ checkIntegrity: true, awaitAll: true })
await Promise.all([didEnterOutOfSync, didExitOutOfSync])
expect(this.application.sync.isOutOfSync()).to.equal(false)
expect(application.sync.isOutOfSync()).to.equal(false)
})
})

View File

@@ -1,11 +1,12 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable no-undef */
import * as Factory from '../lib/factory.js'
import { createRelatedNoteTagPairPayload } from '../lib/Items.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('notes + tags syncing', function () {
let application
const syncOptions = {
checkIntegrity: true,
awaitAll: true,
@@ -16,30 +17,31 @@ describe('notes + tags syncing', function () {
})
beforeEach(async function () {
this.application = await Factory.createInitAppWithFakeCrypto()
Factory.disableIntegrityAutoHeal(this.application)
application = await Factory.createInitAppWithFakeCrypto()
Factory.disableIntegrityAutoHeal(application)
const email = UuidGenerator.GenerateUuid()
const password = UuidGenerator.GenerateUuid()
await Factory.registerUserToApplication({
application: this.application,
application: application,
email,
password,
})
})
afterEach(async function () {
await Factory.safeDeinit(this.application)
await Factory.safeDeinit(application)
application = undefined
})
it('syncing an item then downloading it should include items_key_id', async function () {
const note = await Factory.createMappedNote(this.application)
await this.application.mutator.setItemDirty(note)
await this.application.sync.sync(syncOptions)
await this.application.payloads.resetState()
await this.application.items.resetState()
await this.application.sync.clearSyncPositionTokens()
await this.application.sync.sync(syncOptions)
const downloadedNote = this.application.items.getDisplayableNotes()[0]
const note = await Factory.createMappedNote(application)
await application.mutator.setItemDirty(note)
await application.sync.sync(syncOptions)
await application.payloads.resetState()
await application.items.resetState()
await application.sync.clearSyncPositionTokens()
await application.sync.sync(syncOptions)
const downloadedNote = application.items.getDisplayableNotes()[0]
expect(downloadedNote.items_key_id).to.not.be.ok
// Allow time for waitingForKey
await Factory.sleep(0.1)
@@ -52,21 +54,21 @@ describe('notes + tags syncing', function () {
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = this.application.items.getItems([ContentType.TYPES.Note])[0]
const tag = this.application.items.getItems([ContentType.TYPES.Tag])[0]
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
await application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const note = application.items.getItems([ContentType.TYPES.Note])[0]
const tag = application.items.getItems([ContentType.TYPES.Tag])[0]
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
for (let i = 0; i < 9; i++) {
await this.application.mutator.setItemsDirty([note, tag])
await this.application.sync.sync(syncOptions)
this.application.sync.clearSyncPositionTokens()
await application.mutator.setItemsDirty([note, tag])
await application.sync.sync(syncOptions)
application.sync.clearSyncPositionTokens()
expect(tag.content.references.length).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
expect(tag.noteCount).to.equal(1)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
console.warn('Waiting 0.1s...')
await Factory.sleep(0.1)
}
@@ -76,59 +78,59 @@ describe('notes + tags syncing', function () {
const pair = createRelatedNoteTagPairPayload()
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const originalNote = this.application.items.getDisplayableNotes()[0]
const originalTag = this.application.items.getDisplayableTags()[0]
await this.application.mutator.setItemsDirty([originalNote, originalTag])
await application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
const originalNote = application.items.getDisplayableNotes()[0]
const originalTag = application.items.getDisplayableTags()[0]
await application.mutator.setItemsDirty([originalNote, originalTag])
await this.application.sync.sync(syncOptions)
await application.sync.sync(syncOptions)
expect(originalTag.content.references.length).to.equal(1)
expect(originalTag.noteCount).to.equal(1)
expect(this.application.items.itemsReferencingItem(originalNote).length).to.equal(1)
expect(application.items.itemsReferencingItem(originalNote).length).to.equal(1)
// when signing in, all local items are cleared from storage (but kept in memory; to clear desktop logs),
// then resaved with alternated uuids.
await this.application.storage.clearAllPayloads()
await this.application.sync.markAllItemsAsNeedingSyncAndPersist()
await application.storage.clearAllPayloads()
await application.sync.markAllItemsAsNeedingSyncAndPersist()
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
const note = this.application.items.getDisplayableNotes()[0]
const tag = this.application.items.getDisplayableTags()[0]
const note = application.items.getDisplayableNotes()[0]
const tag = application.items.getDisplayableTags()[0]
expect(tag.content.references.length).to.equal(1)
expect(note.content.references.length).to.equal(0)
expect(tag.noteCount).to.equal(1)
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
})
it('duplicating a tag should maintian its relationships', async function () {
const pair = createRelatedNoteTagPairPayload()
const notePayload = pair[0]
const tagPayload = pair[1]
await this.application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
let note = this.application.items.getDisplayableNotes()[0]
let tag = this.application.items.getDisplayableTags()[0]
expect(this.application.items.itemsReferencingItem(note).length).to.equal(1)
await application.mutator.emitItemsFromPayloads([notePayload, tagPayload], PayloadEmitSource.LocalChanged)
let note = application.items.getDisplayableNotes()[0]
let tag = application.items.getDisplayableTags()[0]
expect(application.items.itemsReferencingItem(note).length).to.equal(1)
await this.application.mutator.setItemsDirty([note, tag])
await this.application.sync.sync(syncOptions)
await this.application.sync.clearSyncPositionTokens()
await application.mutator.setItemsDirty([note, tag])
await application.sync.sync(syncOptions)
await application.sync.clearSyncPositionTokens()
note = this.application.items.findItem(note.uuid)
tag = this.application.items.findItem(tag.uuid)
note = application.items.findItem(note.uuid)
tag = application.items.findItem(tag.uuid)
expect(note.dirty).to.equal(false)
expect(tag.dirty).to.equal(false)
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(1)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(1)
await Factory.changePayloadTimeStampAndSync(
this.application,
application,
tag.payload,
Factory.dateToMicroseconds(Factory.yesterday()),
{
@@ -137,13 +139,13 @@ describe('notes + tags syncing', function () {
syncOptions,
)
tag = this.application.items.findItem(tag.uuid)
tag = application.items.findItem(tag.uuid)
// tag should now be conflicted and a copy created
expect(this.application.items.getDisplayableNotes().length).to.equal(1)
expect(this.application.items.getDisplayableTags().length).to.equal(2)
expect(application.items.getDisplayableNotes().length).to.equal(1)
expect(application.items.getDisplayableTags().length).to.equal(2)
const tags = this.application.items.getDisplayableTags()
const tags = application.items.getDisplayableTags()
const conflictedTag = tags.find((tag) => {
return !!tag.content.conflict_of
})
@@ -157,11 +159,11 @@ describe('notes + tags syncing', function () {
expect(conflictedTag.content.conflict_of).to.equal(originalTag.uuid)
expect(conflictedTag.noteCount).to.equal(originalTag.noteCount)
expect(this.application.items.itemsReferencingItem(conflictedTag).length).to.equal(0)
expect(this.application.items.itemsReferencingItem(originalTag).length).to.equal(0)
expect(application.items.itemsReferencingItem(conflictedTag).length).to.equal(0)
expect(application.items.itemsReferencingItem(originalTag).length).to.equal(0)
// Two tags now link to this note
const referencingItems = this.application.items.itemsReferencingItem(note)
const referencingItems = application.items.itemsReferencingItem(note)
expect(referencingItems.length).to.equal(2)
expect(referencingItems[0]).to.not.equal(referencingItems[1])
}).timeout(10000)

View File

@@ -1,71 +1,70 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable no-undef */
import { BaseItemCounts } from '../lib/BaseItemCounts.js'
import * as Factory from '../lib/factory.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('offline syncing', () => {
let context
let application
let expectedItemCount
const syncOptions = {
checkIntegrity: true,
awaitAll: true,
}
beforeEach(async function () {
this.expectedItemCount = BaseItemCounts.DefaultItems
this.context = await Factory.createAppContext()
await this.context.launch()
this.application = this.context.application
localStorage.clear()
expectedItemCount = BaseItemCounts.DefaultItems
context = await Factory.createAppContext()
await context.launch()
application = context.application
})
afterEach(async function () {
expect(this.application.sync.isOutOfSync()).to.equal(false)
await Factory.safeDeinit(this.application)
})
before(async function () {
localStorage.clear()
})
after(async function () {
expect(application.sync.isOutOfSync()).to.equal(false)
await Factory.safeDeinit(application)
localStorage.clear()
application = undefined
context = undefined
})
it('uuid alternation should delete original payload', async function () {
const note = await Factory.createMappedNote(this.application)
this.expectedItemCount++
const note = await Factory.createMappedNote(application)
expectedItemCount++
await Factory.alternateUuidForItem(this.application, note.uuid)
await this.application.sync.sync(syncOptions)
await Factory.alternateUuidForItem(application, note.uuid)
await application.sync.sync(syncOptions)
const notes = this.application.items.getDisplayableNotes()
const notes = application.items.getDisplayableNotes()
expect(notes.length).to.equal(1)
expect(notes[0].uuid).to.not.equal(note.uuid)
const items = this.application.items.allTrackedItems()
expect(items.length).to.equal(this.expectedItemCount)
const items = application.items.allTrackedItems()
expect(items.length).to.equal(expectedItemCount)
})
it('should sync item with no passcode', async function () {
let note = await Factory.createMappedNote(this.application)
expect(Uuids(this.application.items.getDirtyItems()).includes(note.uuid))
let note = await Factory.createMappedNote(application)
expect(Uuids(application.items.getDirtyItems()).includes(note.uuid))
await this.application.sync.sync(syncOptions)
await application.sync.sync(syncOptions)
note = this.application.items.findItem(note.uuid)
note = application.items.findItem(note.uuid)
/** In rare cases a sync can complete so fast that the dates are equal; this is ok. */
expect(note.lastSyncEnd).to.be.at.least(note.lastSyncBegan)
this.expectedItemCount++
expectedItemCount++
expect(this.application.items.getDirtyItems().length).to.equal(0)
expect(application.items.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(this.expectedItemCount)
const rawPayloads2 = await application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(expectedItemCount)
const itemsKeyRaw = (await Factory.getStoragePayloadsOfType(this.application, ContentType.TYPES.ItemsKey))[0]
const noteRaw = (await Factory.getStoragePayloadsOfType(this.application, ContentType.TYPES.Note))[0]
const itemsKeyRaw = (await Factory.getStoragePayloadsOfType(application, ContentType.TYPES.ItemsKey))[0]
const noteRaw = (await Factory.getStoragePayloadsOfType(application, ContentType.TYPES.Note))[0]
/** Encrypts with default items key */
expect(typeof noteRaw.content).to.equal('string')
@@ -75,30 +74,30 @@ describe('offline syncing', () => {
})
it('should sync item encrypted with passcode', async function () {
await this.application.addPasscode('foobar')
await Factory.createMappedNote(this.application)
expect(this.application.items.getDirtyItems().length).to.equal(1)
const rawPayloads1 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads1.length).to.equal(this.expectedItemCount)
await application.addPasscode('foobar')
await Factory.createMappedNote(application)
expect(application.items.getDirtyItems().length).to.equal(1)
const rawPayloads1 = await application.storage.getAllRawPayloads()
expect(rawPayloads1.length).to.equal(expectedItemCount)
await this.application.sync.sync(syncOptions)
this.expectedItemCount++
await application.sync.sync(syncOptions)
expectedItemCount++
expect(this.application.items.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await this.application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(this.expectedItemCount)
expect(application.items.getDirtyItems().length).to.equal(0)
const rawPayloads2 = await application.storage.getAllRawPayloads()
expect(rawPayloads2.length).to.equal(expectedItemCount)
const payload = rawPayloads2[0]
expect(typeof payload.content).to.equal('string')
expect(payload.content.startsWith(this.application.encryption.getLatestVersion())).to.equal(true)
expect(payload.content.startsWith(application.encryption.getLatestVersion())).to.equal(true)
})
it('signing out while offline should succeed', async function () {
await Factory.createMappedNote(this.application)
this.expectedItemCount++
await this.application.sync.sync(syncOptions)
this.application = await Factory.signOutApplicationAndReturnNew(this.application)
expect(this.application.sessions.isSignedIn()).to.equal(false)
expect(this.application.sessions.getUser()).to.not.be.ok
await Factory.createMappedNote(application)
expectedItemCount++
await application.sync.sync(syncOptions)
application = await Factory.signOutApplicationAndReturnNew(application)
expect(application.sessions.isSignedIn()).to.equal(false)
expect(application.sessions.getUser()).to.not.be.ok
})
})

File diff suppressed because it is too large Load Diff