Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fix several type errors in core manager tests #603

Merged
merged 1 commit into from
May 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions tests/core-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import { waitForCores } from './helpers/core-manager.js'
import { drizzle } from 'drizzle-orm/better-sqlite3'
import { coresTable } from '../src/schema/project.js'
import { eq } from 'drizzle-orm'
/** @typedef {import('../src/constants.js').NAMESPACES[number]} Namespace */

/** @param {any} [key] */
async function createCore(key) {
const core = new Hypercore(RAM, key)
const core = new Hypercore(() => new RAM(), key)
await core.ready()
return core
}
Expand All @@ -38,7 +40,7 @@ test('project creator auth core has project key', async function (t) {

const cm = createCoreManager({
keyManager,
storage: RAM,
storage: () => new RAM(),
projectKey,
projectSecretKey,
})
Expand Down Expand Up @@ -77,14 +79,15 @@ test('eagerly updates remote bitfields', async function (t) {

await waitForCores(cm2, [cm1Core.key])
const cm2Core = cm2.getCoreByKey(cm1Core.key)
t.ok(cm2Core, 'writer core has replicated')
assert(cm2Core, 'writer core has replicated')

// Need to wait for now, since no event for when a remote bitfield is updated
await new Promise((res) => setTimeout(res, 200))

t.is(cm2Core.length, cm1Core.length)

{
assert(cm1Core.core)
// This is testing that the remote bitfield is a duplicate of the bitfield
// on the core that is being replicated, prior to calling core.download()
t.ok(
Expand All @@ -109,6 +112,7 @@ test('eagerly updates remote bitfields', async function (t) {
const { destroy } = replicate(cm1, cm2)
// Need to wait for now, since no event for when a remote bitfield is updated
await new Promise((res) => setTimeout(res, 200))
assert(cm2Core.core)
t.ok(
bitfieldEquals(
cm1Core.peers[0].remoteBitfield,
Expand All @@ -130,6 +134,7 @@ test('eagerly updates remote bitfields', async function (t) {
await new Promise((res) => setTimeout(res, 200))

const cm3Core = cm3.getCoreByKey(cm1Core.key)
assert(cm3Core)
t.alike(cm3Core.length, cm1Core.length)

t.ok(
Expand Down Expand Up @@ -216,7 +221,7 @@ test('Added cores are persisted', async (t) => {
const cm1 = createCoreManager({
db,
keyManager,
storage: RAM,
storage: () => new RAM(),
projectKey,
})
const key = randomBytes(32)
Expand All @@ -227,14 +232,15 @@ test('Added cores are persisted', async (t) => {
const cm2 = createCoreManager({
db,
keyManager,
storage: RAM,
storage: () => new RAM(),
projectKey,
})

t.ok(cm2.getCoreByKey(key), 'Added core is persisted')
})

test('encryption', async function (t) {
/** @type {Partial<Record<Namespace, Buffer>>} */
const encryptionKeys = {}
for (const ns of CoreManager.namespaces) {
encryptionKeys[ns] = randomBytes(32)
Expand Down Expand Up @@ -265,6 +271,7 @@ test('poolSize limits number of open file descriptors', async function (t) {

const CORE_COUNT = 500
await temporaryDirectoryTask(async (tempPath) => {
/** @param {string} name */
const storage = (name) => new RandomAccessFile(path.join(tempPath, name))
const cm = createCoreManager({
keyManager,
Expand All @@ -287,6 +294,7 @@ test('poolSize limits number of open file descriptors', async function (t) {
await temporaryDirectoryTask(async (tempPath) => {
const POOL_SIZE = 100
const pool = new RandomAccessFilePool(POOL_SIZE)
/** @param {string} name */
const storage = (name) =>
new RandomAccessFile(path.join(tempPath, name), { pool })
const cm = createCoreManager({
Expand Down Expand Up @@ -367,12 +375,12 @@ test('sends "haves" bitfields over project creator core replication stream', asy
// Need to wait for now, since no event for when a remote bitfield is updated
await new Promise((res) => setTimeout(res, 200))

const peerId = n1.publicKey.toString('hex')
const peerId = n1.publicKey?.toString('hex') || ''
const havesByNamespace = havesByPeer.get(peerId)
const havesByCore = havesByNamespace.get('data')
t.ok(havesByCore)
const bitfield = havesByCore.get(cm1Core.discoveryKey.toString('hex'))
t.ok(bitfield)
const havesByCore = havesByNamespace?.get('data')
const bitfield = havesByCore?.get(cm1Core.discoveryKey?.toString('hex') || '')
assert(bitfield)
assert(cm1Core.core)

t.ok(
bitfieldEquals(bitfield, cm1Core.core.bitfield, cm1Core.length),
Expand All @@ -395,7 +403,7 @@ test('unreplicate', async (t) => {
const [s1, s2] = replicateCores(a, b, t, { delay: REPLICATION_DELAY })

const block1 = await b.get(0, { timeout: WAIT_TIMEOUT })
st.is(block1.toString(), 'a')
st.is(block1?.toString(), 'a')

await unreplicate(a, s1.noiseStream.userData)

Expand All @@ -407,7 +415,7 @@ test('unreplicate', async (t) => {
b.replicate(s2)

const block2 = await b.get(1, { timeout: WAIT_TIMEOUT })
st.is(block2.toString(), 'b')
st.is(block2?.toString(), 'b')
})
await t.test(
'initiator unreplicates, initiator re-replicates',
Expand All @@ -419,7 +427,7 @@ test('unreplicate', async (t) => {
const [s1] = replicateCores(a, b, t, { delay: REPLICATION_DELAY })

const block1 = await b.get(0, { timeout: WAIT_TIMEOUT })
st.is(block1.toString(), 'a')
st.is(block1?.toString(), 'a')

await unreplicate(a, s1.noiseStream.userData)

Expand All @@ -431,7 +439,7 @@ test('unreplicate', async (t) => {
a.replicate(s1)

const block2 = await b.get(1, { timeout: WAIT_TIMEOUT })
st.is(block2.toString(), 'b')
st.is(block2?.toString(), 'b')
}
)
await t.test('receiver unreplicates, receiver re-replicates', async (st) => {
Expand All @@ -442,7 +450,7 @@ test('unreplicate', async (t) => {
const [, s2] = replicateCores(a, b, t, { delay: REPLICATION_DELAY })

const block1 = await b.get(0, { timeout: WAIT_TIMEOUT })
st.is(block1.toString(), 'a')
st.is(block1?.toString(), 'a')

await unreplicate(b, s2.noiseStream.userData)

Expand All @@ -454,7 +462,7 @@ test('unreplicate', async (t) => {
b.replicate(s2)

const block2 = await b.get(1, { timeout: WAIT_TIMEOUT })
st.is(block2.toString(), 'b')
st.is(block2?.toString(), 'b')
})
})

Expand Down Expand Up @@ -626,8 +634,15 @@ test('deleteOthersData()', async (t) => {

const DEBUG = process.env.DEBUG

// Compare two bitfields (instance of core.core.bitfield or peer.remoteBitfield)
// Need to pass len, since bitfields don't know their own length
/**
* Compare two bitfields (instance of core.core.bitfield or peer.remoteBitfield)
* Need to pass len, since bitfields don't know their own length
*
* @param {{ get(index: number): unknown }} actual
* @param {{ get(index: number): unknown }} expected
* @param {number} len
* @returns {boolean}
*/
function bitfieldEquals(actual, expected, len) {
assert(typeof len === 'number')
let actualStr = ''
Expand Down Expand Up @@ -666,11 +681,18 @@ async function countOpenFileDescriptors(dir) {
return new Promise((res, rej) => {
exec(`lsof +D '${dir}' | wc -l`, (error, stdout) => {
if (error) return rej(error)
res(stdout - 1)
res(Number(stdout) - 1)
})
})
}

/**
* @param {Hypercore} a
* @param {Hypercore} b
* @param {import('brittle').TestInstance} t
* @param {Parameters<typeof Hypercore.prototype.replicate>[1] & { delay?: number }} [opts]
* @returns
*/
function replicateCores(a, b, t, { delay = 0, ...opts } = {}) {
const s1 = a.replicate(true, { keepAlive: false, ...opts })
const s2 = b.replicate(false, { keepAlive: false, ...opts })
Expand Down
Loading