Skip to content

Commit

Permalink
test: add loop call order tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andretchen0 committed Jun 22, 2024
1 parent 543fbfa commit 7fa0430
Showing 1 changed file with 155 additions and 1 deletion.
156 changes: 155 additions & 1 deletion src/core/loop.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { afterEach, beforeEach, it } from 'vitest'
import type { TresContext } from '../composables/useTresContextProvider'
import { createRenderLoop } from './loop'

let renderLoop

describe('createRenderLoop', () => {
beforeEach(() => {
renderLoop = createRenderLoop()
renderLoop = createRenderLoop({} as TresContext)
})
afterEach(() => {
renderLoop.stop()
Expand Down Expand Up @@ -117,4 +118,157 @@ describe('createRenderLoop', () => {

expect(executionOrder).toEqual(['before', 'fbo', 'render', 'after'])
})

describe('`stop`, `start`, `pause`, `resume` call order', () => {
it('does not trigger a callback on `start()` unless `stop()`ped', () => {
const callbackBefore = vi.fn()
const callbackRender = vi.fn()
const callbackAfter = vi.fn()
renderLoop.register(callbackBefore, 'before')
renderLoop.register(callbackRender, 'render')
renderLoop.register(callbackAfter, 'after')
renderLoop.start()
expect(callbackBefore).toBeCalledTimes(1)
expect(callbackRender).toBeCalledTimes(1)
expect(callbackAfter).toBeCalledTimes(1)

renderLoop.start()
renderLoop.start()
renderLoop.start()
renderLoop.start()
expect(callbackBefore).toBeCalledTimes(1)
expect(callbackRender).toBeCalledTimes(1)
expect(callbackAfter).toBeCalledTimes(1)

renderLoop.stop()
renderLoop.start()
expect(callbackBefore).toBeCalledTimes(2)
expect(callbackRender).toBeCalledTimes(2)
expect(callbackAfter).toBeCalledTimes(2)
})

it('can `start()` even if `resume()`d while `stop()`ped', () => {
const callbackBefore = vi.fn()
const callbackRender = vi.fn()
const callbackAfter = vi.fn()
renderLoop.register(callbackBefore, 'before')
renderLoop.register(callbackRender, 'render')
renderLoop.register(callbackAfter, 'after')
renderLoop.stop()
renderLoop.resume()
expect(callbackBefore).toBeCalledTimes(0)
expect(callbackRender).toBeCalledTimes(0)
expect(callbackAfter).toBeCalledTimes(0)

renderLoop.start()
expect(callbackBefore).toBeCalledTimes(1)
expect(callbackRender).toBeCalledTimes(1)
expect(callbackAfter).toBeCalledTimes(1)
})

it('`isActive.value` is `true` only if both `start()`ed and `resume()`d, regardless of call order', () => {
const callbackBefore = vi.fn()
const callbackRender = vi.fn()
const callbackAfter = vi.fn()
renderLoop.register(callbackBefore, 'before')
renderLoop.register(callbackRender, 'render')
renderLoop.register(callbackAfter, 'after')

const { start, stop, resume, pause } = renderLoop

// NOTE: stop, pause | stop, resume | start, resume
// NOTE: stop, pause
stop()
pause()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: stop, resume
resume()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: start, resume
start()
expect(renderLoop.isActive.value).toBe(true)

// NOTE: stop, pause | start, pause | start, resume
// NOTE: stop, pause
stop()
pause()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: start, pause
start()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: start, resume
resume()
expect(renderLoop.isActive.value).toBe(true)

// NOTE: start, resume | start, pause | start, resume
// NOTE: start, resume
resume()
start()
expect(renderLoop.isActive.value).toBe(true)
// NOTE: start, pause
pause()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: start, resume
resume()
expect(renderLoop.isActive.value).toBe(true)

// NOTE: start, resume | stop, resume | start, resume
// NOTE: start, resume
resume()
start()
expect(renderLoop.isActive.value).toBe(true)
// NOTE: stop, resume
stop()
expect(renderLoop.isActive.value).toBe(false)
// NOTE: start, resume
start()
expect(renderLoop.isActive.value).toBe(true)

// NOTE: make some random calls
const ons = [start, resume]
const offs = [stop, pause]
const onsAndOffs = [start, stop, resume, pause]
const TEST_COUNT = 100

for (let i = 0; i < TEST_COUNT; i++) {
const ARRAY_COUNT = 25 + Math.floor(Math.random() * 10)
const _offs = Array.from({ length: ARRAY_COUNT }).fill(0).map(() => choose(offs))
_offs.forEach(fn => fn())
expect(renderLoop.isActive.value).toBe(false)
shuffle(ons)
ons.forEach(fn => fn())
expect(renderLoop.isActive.value).toBe(true)
}

for (let i = 0; i < TEST_COUNT; i++) {
const ARRAY_COUNT = 25 + Math.floor(Math.random() * 10)
const _onsAndOffs = Array.from({ length: ARRAY_COUNT }).fill(0).map(() => choose(onsAndOffs))
_onsAndOffs.forEach(fn => fn())
shuffle(offs)
offs[0]()
expect(renderLoop.isActive.value).toBe(false)
shuffle(ons)
ons.forEach(fn => fn())
expect(renderLoop.isActive.value).toBe(true)
}
})
})
})

function choose(array: any[]) {
const i = Math.floor(Math.random() * array.length)
return array[i]
}

function shuffle(array: any[]) {
let currentIndex = array.length
while (currentIndex !== 0) {
const randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
]
}
return array
};

0 comments on commit 7fa0430

Please sign in to comment.