Skip to content

Commit

Permalink
split up purge-stale-exhaustive test to go fast
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Mar 17, 2022
1 parent 258e422 commit 23708c7
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 66 deletions.
93 changes: 93 additions & 0 deletions test/purge-stale-exhaustive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
if (typeof performance === 'undefined') {
global.performance = require('perf_hooks').performance
}

const t = require('tap')
const Clock = require('clock-mock')
const clock = new Clock()
clock.advance(1)

const boolOpts = n => {
const mask = Math.pow(2, n)
const arr = []
for (let i = 0; i < mask; i++) {
arr.push((mask + i).toString(2).slice(1).split('').map(n => +n))
}
return arr
}

const permute = arr => {
if (typeof arr === 'number') {
return permute(Object.keys(new Array(arr).fill('')).map(n => +n))
}
if (arr.length === 1) {
return [arr]
}
const permutations = []
// recurse over selecting any of the items
for (let i = 0; i < arr.length; i++) {
const items = arr.slice(0)
const item = items.splice(i, 1)
permutations.push(...permute(items).map(perm => item.concat(perm)))
}
return permutations
}

const runTestStep = ({order, stales = -1, len}) => {
// generate stales at this level because it's faster that way,
// fewer tap pieces to prop it all up.
if (stales === -1) {
for (const stales of boolOpts(len)) {
runTestStep({order, stales, len})
}
return true
}

clock.enter()
const assert = require('assert')
const LRU = require('../')
const c = new LRU({ max: len, ttl: 100 })
// fill the array with index matching k/v
for (let i = 0; i < len; i++) {
if (stales[i]) {
c.set(i, i, { ttl: 1 })
} else {
c.set(i, i)
}
}

// now get() items to reorder
for (const index of order) {
c.get(index)
}

assert.deepEqual([...c.rindexes()], order, 'got expected ordering')

// advance clock so masked go stale
clock.advance(10)
c.purgeStale()
assert.deepEqual([...c.rindexes()], [...c.rindexes({ allowStale: true })])
// make all go stale
clock.advance(100)
c.purgeStale()
assert.deepEqual([...c.rindexes({ allowStale: true })], [])
clock.exit()
return true
}

t.test('exhaustive tests', t => {
// this is a brutal test.
// Generate every possible ordering of indexes.
// then for each ordering, generate every possible arrangement of staleness
// Verify that purgeStale produces the correct result every time.
const len = 5
for (const order of permute(len)) {
const name = `order=${order.join('')}`
t.test(name, t => {
t.plan(1)
runTestStep({order, len})
t.pass('no problems')
})
}
t.end()
})
66 changes: 0 additions & 66 deletions test/ttl.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,72 +357,6 @@ const runTests = (LRU, t) => {
t.end()
})

t.test('purgeStale() lockup exhaustive', { bail: true }, t => {
// this is a brutal test.
// Generate every possible ordering of indexes.
// then for each ordering, generate every possible arrangement of staleness
// Verify that purgeStale produces the correct result every time.
const len = 5
const permute = arr => {
if (typeof arr === 'number') {
return permute(Object.keys(new Array(len).fill('')).map(n => +n))
}
if (arr.length === 1) {
return [arr]
}
const permutations = []
// recurse over selecting any of the items
for (let i = 0; i < arr.length; i++) {
const items = arr.slice(0)
const item = items.splice(i, 1)
permutations.push(...permute(items).map(perm => item.concat(perm)))
}
return permutations
}
// generate every possible set of true/false for a given length
const boolOpts = n => {
const mask = Math.pow(2, n)
const arr = []
for (let i = 0; i < mask; i++) {
arr.push((mask + i).toString(2).slice(1).split('').map(n => +n))
}
return arr
}
for (const order of permute(len)) {
t.test('order=' + order.join(','), t => {
for (const stales of boolOpts(len)) {
t.test('stalemask=' + stales.join(''), t => {
const c = new LRU({ max: len, ttl: 100 })
// fill the array with index matching k/v
for (let i = 0; i < len; i++) {
if (stales[i]) {
c.set(i, i, { ttl: 1 })
} else {
c.set(i, i)
}
}
// now get() items to reorder
for (const index of order) {
c.get(index)
}
t.same([...c.rindexes()], order, 'got expected ordering')

// advance clock so masked go stale
clock.advance(10)
c.purgeStale()
t.same([...c.rindexes()], [...c.rindexes({ allowStale: true })])
// make all go stale
clock.advance(100)
c.purgeStale()
t.same([...c.rindexes({ allowStale: true })], [])
t.end()
})
}
t.end()
})
}
t.end()
})
t.end()
}

Expand Down

0 comments on commit 23708c7

Please sign in to comment.