Skip to content

Commit

Permalink
refactor index
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Razon committed Sep 11, 2023
1 parent c183d65 commit 86c390a
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 4 deletions.
171 changes: 171 additions & 0 deletions tunnel-server/src/tunnel-store/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { describe, it, expect, beforeEach } from '@jest/globals'
import pinoPretty from 'pino-pretty'
import { Logger, pino } from 'pino'
import { ActiveTunnel, ActiveTunnelStore, TransactionDescriptor, inMemoryActiveTunnelStore } from '.'

describe('inMemoryActiveTunnelStore', () => {
let store: ActiveTunnelStore
let log: Logger

beforeEach(() => {
log = pino({ level: 'debug' }, pinoPretty())
store = inMemoryActiveTunnelStore({ log })
})

describe('when setting a new key', () => {
let desc: TransactionDescriptor
let val: ActiveTunnel
beforeEach(async () => {
val = { publicKeyThumbprint: 'pk1' } as ActiveTunnel
desc = await store.set('foo', val)
})

it('returns a descriptor', async () => {
expect(desc).toBeDefined()
})

describe('when getting a non-existant key', () => {
it('returns undefined', async () => {
expect(await store.get('bar')).toBeUndefined()
})
})

describe('when getting a non-existing value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk2')
})

it('returns undefined', () => {
expect(gotValAr).toBeUndefined()
})
})

describe('when getting the key', () => {
let gotVal: ActiveTunnel | undefined
beforeEach(async () => {
gotVal = await store.get('foo')
})

it('returns the value', () => {
expect(gotVal).toBe(val)
})
})

describe('when getting an existing value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk1')
})

it('returns the value', () => {
expect(gotValAr).toHaveLength(1)
expect(gotValAr).toContain(val)
})
})

describe('when deleting a non-existant value', () => {
beforeEach(async () => {
await store.delete('bar')
})

describe('when getting a non-existing value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk2')
})

it('returns undefined', () => {
expect(gotValAr).toBeUndefined()
})
})

describe('when getting an existing value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk1')
})

it('returns the value', () => {
expect(gotValAr).toHaveLength(1)
expect(gotValAr).toContain(val)
})
})
})

describe('when deleting an existing value without a tx arg', () => {
beforeEach(async () => {
await store.delete('foo')
})

describe('when getting the deleted key', () => {
it('returns undefined', async () => {
expect(await store.get('foo')).toBeUndefined()
})
})

describe('when getting a the deleted value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk1')
})

it('returns undefined', () => {
expect(gotValAr).toBeUndefined()
})
})
})

describe('when deleting an existing value with a correct tx arg', () => {
beforeEach(async () => {
await store.delete('foo', desc)
})

describe('when getting the deleted key', () => {
it('returns undefined', async () => {
expect(await store.get('foo')).toBeUndefined()
})
})

describe('when getting a the deleted value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk1')
})

it('returns undefined', () => {
expect(gotValAr).toBeUndefined()
})
})
})

describe('when deleting an existing value with an incorrect tx arg', () => {
beforeEach(async () => {
await store.delete('foo', { txId: -1 })
})

describe('when getting the key', () => {
let gotVal: ActiveTunnel | undefined
beforeEach(async () => {
gotVal = await store.get('foo')
})

it('returns the value', () => {
expect(gotVal).toBe(val)
})
})

describe('when getting the value by thumbprint', () => {
let gotValAr: readonly ActiveTunnel[] | undefined
beforeEach(async () => {
gotValAr = await store.getByPkThumbprint('pk1')
})

it('returns the value', () => {
expect(gotValAr).toHaveLength(1)
expect(gotValAr).toContain(val)
})
})
})
})
})
9 changes: 5 additions & 4 deletions tunnel-server/src/tunnel-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,26 @@ const idGenerator = () => {

export const inMemoryActiveTunnelStore = ({ log }: { log: Logger }): ActiveTunnelStore => {
const keyToTunnel = new Map<string, ActiveTunnel & { txId: number }>()
const pkThumbprintToTunnel = arrayMap<string, ActiveTunnel>()
const pkThumbprintToTunnel = arrayMap<string, string>()
const txIdGen = idGenerator()
return {
get: async key => keyToTunnel.get(key),
getByPkThumbprint: async pkThumbprint => pkThumbprintToTunnel.get(pkThumbprint),
getByPkThumbprint: async pkThumbprint => pkThumbprintToTunnel.get(pkThumbprint)
?.map(key => keyToTunnel.get(key) as ActiveTunnel),
set: async (key, value) => {
if (keyToTunnel.has(key)) {
throw new KeyAlreadyExistsError(key)
}
const txId = txIdGen.next()
log.debug('setting tunnel key %s id %s: %j', key, txId, value)
keyToTunnel.set(key, Object.assign(value, { txId }))
pkThumbprintToTunnel.add(value.publicKeyThumbprint, value)
pkThumbprintToTunnel.add(value.publicKeyThumbprint, key)
return { txId }
},
delete: async (key, tx) => {
const tunnel = keyToTunnel.get(key)
if (tunnel && (tx === undefined || tunnel.txId === tx.txId)) {
pkThumbprintToTunnel.delete(tunnel.publicKeyThumbprint, ({ hostname }) => hostname === key)
pkThumbprintToTunnel.delete(tunnel.publicKeyThumbprint, k => k === key)
keyToTunnel.delete(key)
}
},
Expand Down

0 comments on commit 86c390a

Please sign in to comment.