Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 4 additions & 4 deletions developer-docs/testing-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ It would seem like the best order in which to use the control flow utilities is
1. Simply await a Promise if possible and relevant
2. `waitForStreamToEnd` if dealing with ReadableStream
3. `waitForEvent` if dealing with events
4. `waitForCondition` when there is no direct handle to the async-behavior
4. `until` when there is no direct handle to the async-behavior
5. `wait` if nothing else works

### Try to avoid using `wait` when possible.
Expand All @@ -15,10 +15,10 @@ It would seem like the best order in which to use the control flow utilities is
- It increases test run time because we always wait for the pre-determined amount of time even if the required pre-condition has been met.
- We often have to use quite large delays to err on the side of caution, increasing test run time further.

### When using `waitForCondition` favor simple conditions
### When using `until` favor simple conditions
- The utility doesn't provide detailed info on what went wrong; when a condition fails, you will not have much visibility into the "why".
- Use a simple condition for `waitForCondition` and then later on in the test function perform proper assertions using the facilities provided by your test framework.
- E.g. use `waitForCondition` to wait for an array to have elements in it. Then afterwards assert the contents of those elements.
- Use a simple condition for `until` and then later on in the test function perform proper assertions using the facilities provided by your test framework.
- E.g. use `until` to wait for an array to have elements in it. Then afterwards assert the contents of those elements.

### Other
- Usefulness of `waitForEvent` declines in the presence of multiple events from the same emitter with the same event type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
toDhtAddressRaw
} from '@streamr/dht'
import path from 'path'
import { MetricsContext, waitForCondition } from '@streamr/utils'
import { MetricsContext, until } from '@streamr/utils'

describe('StreamrChallenger', () => {

Expand Down Expand Up @@ -68,7 +68,7 @@ describe('StreamrChallenger', () => {

it('Happy path', async () => {
await runStreamrChallenge('127.0.0.1', '12323', sessionId)
await waitForCondition(() => challengedClientTransport.getConnections().length === 0)
await until(() => challengedClientTransport.getConnections().length === 0)
})

})
6 changes: 3 additions & 3 deletions packages/cli-tools/test/storage-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { fetchPrivateKeyWithGas } from '@streamr/test-utils'
import 'jest-extended'
import { StreamID } from '@streamr/sdk'
import { DOCKER_DEV_STORAGE_NODE, createTestClient, runCommand } from './utils'
import { waitForCondition } from '@streamr/utils'
import { until } from '@streamr/utils'

const isStored = async (streamId: StreamID): Promise<boolean> => {
const output = await runCommand(`storage-node list-streams ${DOCKER_DEV_STORAGE_NODE}`)
Expand All @@ -19,11 +19,11 @@ describe('storage node', () => {
await runCommand(`storage-node add-stream ${DOCKER_DEV_STORAGE_NODE} ${stream.id}`, {
privateKey
})
await waitForCondition(async () => await isStored(stream.id) === true, 15 * 1000, 1000)
await until(async () => await isStored(stream.id) === true, 15 * 1000, 1000)
await runCommand(`storage-node remove-stream ${DOCKER_DEV_STORAGE_NODE} ${stream.id}`, {
privateKey
})
await waitForCondition(async () => await isStored(stream.id) === false, 15 * 1000, 1000)
await until(async () => await isStored(stream.id) === false, 15 * 1000, 1000)
}, 80 * 1000)

it('list nodes', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-tools/test/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Stream, StreamrClient } from '@streamr/sdk'
import { collect, waitForCondition } from '@streamr/utils'
import { collect, until } from '@streamr/utils'
import { spawn } from 'child_process'
import merge2 from 'merge2'

Expand Down Expand Up @@ -75,7 +75,7 @@ export const createTestClient = (privateKey?: string): StreamrClient => {
}

export const waitForTheGraphToHaveIndexed = async (stream: Stream, client: StreamrClient): Promise<void> => {
await waitForCondition(async () => {
await until(async () => {
// eslint-disable-next-line no-underscore-dangle
for await (const _msg of client.searchStreams(stream.id, undefined)) {
return true
Expand Down
4 changes: 2 additions & 2 deletions packages/dht/src/dht/DhtNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
MetricsContext,
merge,
scheduleAtInterval,
waitForCondition
until
} from '@streamr/utils'
import { EventEmitter } from 'eventemitter3'
import { sample } from 'lodash'
Expand Down Expand Up @@ -621,7 +621,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
}

public async waitForNetworkConnectivity(): Promise<void> {
await waitForCondition(
await until(
() => this.connectionsView!.getConnectionCount() > 0,
this.options.networkConnectivityTimeout,
100,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PeerDescriptor } from '../../generated/packages/dht/protos/PeerDescriptor'
import { DhtNode } from '../../src/dht/DhtNode'
import { ConnectionManager } from '../../src/connection/ConnectionManager'
import { waitForCondition } from '@streamr/utils'
import { until } from '@streamr/utils'
import { createMockPeerDescriptor } from '../utils/utils'
import { areEqualPeerDescriptors } from '../../src/identifiers'

Expand Down Expand Up @@ -60,7 +60,7 @@ describe('Websocket IConnection Requests', () => {
await node2.joinDht([epPeerDescriptor])
await node1.joinDht([epPeerDescriptor])

await waitForCondition(() => { return (connected1 && connected2) })
await until(() => { return (connected1 && connected2) })

expect((node1.getTransport() as ConnectionManager).hasConnection(node2.getNodeId())).toEqual(true)
expect((node2.getTransport() as ConnectionManager).hasConnection(node1.getNodeId())).toEqual(true)
Expand Down
4 changes: 2 additions & 2 deletions packages/dht/test/end-to-end/memory-leak.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import LeakDetector from 'jest-leak-detector'
import { waitForCondition } from '@streamr/utils'
import { until } from '@streamr/utils'
import { DhtNode } from '../../src/dht/DhtNode'
import { Message } from '../../generated/packages/dht/protos/DhtRpc'
import { RpcMessage } from '../../generated/packages/proto-rpc/protos/ProtoRpc'
Expand Down Expand Up @@ -55,7 +55,7 @@ describe('memory leak', () => {
}
}
await sender.send(msg)
await waitForCondition(() => receivedMessage !== undefined)
await until(() => receivedMessage !== undefined)
expect(receivedMessage!.messageId).toEqual(MESSAGE_ID)

await Promise.all([
Expand Down
34 changes: 17 additions & 17 deletions packages/dht/test/integration/ConnectionLocking.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MetricsContext, waitForCondition } from '@streamr/utils'
import { MetricsContext, until } from '@streamr/utils'
import { ConnectionManager } from '../../src/connection/ConnectionManager'
import { DefaultConnectorFacade } from '../../src/connection/ConnectorFacade'
import { LatencyType, Simulator } from '../../src/connection/simulator/Simulator'
Expand Down Expand Up @@ -60,7 +60,7 @@ describe('Connection Locking', () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock')
])
expect(connectionManager1.hasConnection(nodeId2)).toEqual(true)
Expand All @@ -72,11 +72,11 @@ describe('Connection Locking', () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock1')
])
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock2')
])
expect(connectionManager1.hasConnection(nodeId2)).toEqual(true)
Expand All @@ -88,7 +88,7 @@ describe('Connection Locking', () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock')
])
expect(connectionManager1.hasConnection(nodeId2))
Expand All @@ -97,19 +97,19 @@ describe('Connection Locking', () => {

connectionManager1.unlockConnection(mockPeerDescriptor2, 'testLock')
expect(connectionManager1.hasLocalLockedConnection(nodeId2)).toEqual(false)
await waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1) === false)
await until(() => connectionManager2.hasRemoteLockedConnection(nodeId1) === false)
expect(connectionManager1.hasConnection(nodeId1)).toEqual(false)
})

it('unlocking multiple services', async () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock1')
])
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock2')
])

Expand All @@ -128,8 +128,8 @@ describe('Connection Locking', () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
waitForCondition(() => connectionManager1.hasRemoteLockedConnection(nodeId2)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager1.hasRemoteLockedConnection(nodeId2)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock1'),
connectionManager2.lockConnection(mockPeerDescriptor1, 'testLock1')
])
Expand All @@ -138,7 +138,7 @@ describe('Connection Locking', () => {
expect(connectionManager2.hasLocalLockedConnection(nodeId1))

connectionManager1.unlockConnection(mockPeerDescriptor2, 'testLock1')
await waitForCondition(() =>
await until(() =>
connectionManager1.hasRemoteLockedConnection(nodeId2)
&& !connectionManager1.hasLocalLockedConnection(nodeId2)
&& !connectionManager2.hasRemoteLockedConnection(nodeId1)
Expand All @@ -153,8 +153,8 @@ describe('Connection Locking', () => {
const nodeId1 = toNodeId(mockPeerDescriptor1)
const nodeId2 = toNodeId(mockPeerDescriptor2)
await Promise.all([
waitForCondition(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
waitForCondition(() => connectionManager1.hasRemoteLockedConnection(nodeId2)),
until(() => connectionManager2.hasRemoteLockedConnection(nodeId1)),
until(() => connectionManager1.hasRemoteLockedConnection(nodeId2)),
connectionManager1.lockConnection(mockPeerDescriptor2, 'testLock1'),
connectionManager2.lockConnection(mockPeerDescriptor1, 'testLock1')
])
Expand All @@ -165,16 +165,16 @@ describe('Connection Locking', () => {
//@ts-expect-error private field
await connectionManager1.gracefullyDisconnectAsync(mockPeerDescriptor2)

await waitForCondition(() =>
await until(() =>
!connectionManager1.hasRemoteLockedConnection(nodeId2)
&& !connectionManager1.hasLocalLockedConnection(nodeId2)
)
await waitForCondition(() =>
await until(() =>
!connectionManager2.hasRemoteLockedConnection(nodeId1)
&& !connectionManager2.hasLocalLockedConnection(nodeId1)
)
await waitForCondition(() => !connectionManager2.hasConnection(nodeId1))
await waitForCondition(() => !connectionManager1.hasConnection(nodeId2))
await until(() => !connectionManager2.hasConnection(nodeId1))
await until(() => !connectionManager1.hasConnection(nodeId2))

expect(connectionManager1.hasConnection(nodeId2)).toEqual(false)
expect(connectionManager2.hasConnection(nodeId1)).toEqual(false)
Expand Down
6 changes: 3 additions & 3 deletions packages/dht/test/integration/ConnectionManager.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, MetricsContext, waitForCondition, waitForEvent3 } from '@streamr/utils'
import { Logger, MetricsContext, until, waitForEvent3 } from '@streamr/utils'
import { MarkOptional } from 'ts-essentials'
import { ConnectionManager } from '../../src/connection/ConnectionManager'
import { DefaultConnectorFacade, DefaultConnectorFacadeOptions } from '../../src/connection/ConnectorFacade'
Expand Down Expand Up @@ -514,11 +514,11 @@ describe('ConnectionManager', () => {
await Promise.all([connectedPromise1, connectedPromise2, connectionManager2.send(msg)])

await connectionManager1.enablePrivateClientMode()
await waitForCondition(() => connectionManager2.getConnections().length === 0)
await until(() => connectionManager2.getConnections().length === 0)
expect(connectionManager1.getConnections().length).toEqual(1)

await connectionManager1.disablePrivateClientMode()
await waitForCondition(() => connectionManager2.getConnections().length === 1)
await until(() => connectionManager2.getConnections().length === 1)
expect(connectionManager1.getConnections().length).toEqual(1)

await connectionManager1.stop()
Expand Down
4 changes: 2 additions & 2 deletions packages/dht/test/integration/DhtNode.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { waitForCondition } from '@streamr/utils'
import { until } from '@streamr/utils'
import { range, without } from 'lodash'
import { DhtNodeRpcLocal } from '../../src/dht/DhtNodeRpcLocal'
import { DhtNode, ListeningRpcCommunicator, toNodeId } from '../../src/exports'
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('DhtNode', () => {
await localNode.joinDht([entryPointPeerDescriptor])
await localNode.waitForNetworkConnectivity()

await waitForCondition(() => localNode.getNeighborCount() === otherPeerDescriptors.length + 1)
await until(() => localNode.getNeighborCount() === otherPeerDescriptors.length + 1)
const expectedNodeIds = without(getAllPeerDescriptors(), localPeerDescriptor).map((n) => toNodeId(n))
const actualNodeIds = localNode.getClosestContacts().map((n) => toNodeId(n))
expect(actualNodeIds).toIncludeSameMembers(expectedNodeIds)
Expand Down
2 changes: 1 addition & 1 deletion packages/dht/test/integration/Layer1-scale.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ describe('Layer1', () => {
// })
// })
//
// await waitForCondition(() => {
// await until(() => {
// return [...receivedMessages.values()].every((set) => {
// return set.size === receivedMessages.size - 1
// })
Expand Down
8 changes: 4 additions & 4 deletions packages/dht/test/integration/RouteMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DhtNode, Events as DhtNodeEvents } from '../../src/dht/DhtNode'
import { Message, RouteMessageWrapper } from '../../generated/packages/dht/protos/DhtRpc'
import { PeerDescriptor, NodeType } from '../../generated/packages/dht/protos/PeerDescriptor'
import { RpcMessage } from '../../generated/packages/proto-rpc/protos/ProtoRpc'
import { Logger, runAndWaitForEvents3, waitForCondition } from '@streamr/utils'
import { Logger, runAndWaitForEvents3, until } from '@streamr/utils'
import { createMockConnectionDhtNode, createWrappedClosestPeersRequest } from '../utils/utils'
import { Simulator } from '../../src/connection/simulator/Simulator'
import { v4 } from 'uuid'
Expand Down Expand Up @@ -117,7 +117,7 @@ describe('Route Message With Mock Connections', () => {
parallelRootNodeIds: []
})
}
await waitForCondition(() => receivedMessages === messageCount)
await until(() => receivedMessages === messageCount)
})

it('From all to all', async () => {
Expand Down Expand Up @@ -158,10 +158,10 @@ describe('Route Message With Mock Connections', () => {
}))
)
)
await waitForCondition(() => receivedMessageCounts[routerNodes[0].getNodeId()] >= routerNodes.length - 1, 30000)
await until(() => receivedMessageCounts[routerNodes[0].getNodeId()] >= routerNodes.length - 1, 30000)
await Promise.all(
Object.keys(receivedMessageCounts).map(async (key) =>
waitForCondition(() => receivedMessageCounts[key as DhtAddress] >= routerNodes.length - 1, 30000)
until(() => receivedMessageCounts[key as DhtAddress] >= routerNodes.length - 1, 30000)
)
)

Expand Down
18 changes: 9 additions & 9 deletions packages/dht/test/integration/SimultaneousConnections.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MetricsContext, waitForCondition } from '@streamr/utils'
import { MetricsContext, until } from '@streamr/utils'
import { ConnectionManager } from '../../src/connection/ConnectionManager'
import { DefaultConnectorFacade, DefaultConnectorFacadeOptions } from '../../src/connection/ConnectorFacade'
import { LatencyType, Simulator } from '../../src/connection/simulator/Simulator'
Expand Down Expand Up @@ -80,8 +80,8 @@ describe('SimultaneousConnections', () => {
simTransport1.send(msg1),
simTransport2.send(msg2)
])
await waitForCondition(() => simTransport2.hasConnection(toNodeId(peerDescriptor1)))
await waitForCondition(() => simTransport1.hasConnection(toNodeId(peerDescriptor2)))
await until(() => simTransport2.hasConnection(toNodeId(peerDescriptor1)))
await until(() => simTransport1.hasConnection(toNodeId(peerDescriptor2)))
})

describe('Websocket 2 servers', () => {
Expand Down Expand Up @@ -161,8 +161,8 @@ describe('SimultaneousConnections', () => {
connectionManager2.send(msg2)
])

await waitForCondition(() => connectionManager1.hasConnection(toNodeId(wsPeerDescriptor2)))
await waitForCondition(() => connectionManager2.hasConnection(toNodeId(wsPeerDescriptor1)))
await until(() => connectionManager1.hasConnection(toNodeId(wsPeerDescriptor2)))
await until(() => connectionManager2.hasConnection(toNodeId(wsPeerDescriptor1)))
})
})

Expand Down Expand Up @@ -241,8 +241,8 @@ describe('SimultaneousConnections', () => {
connectionManager2.send(msg2)
])

await waitForCondition(() => connectionManager1.hasConnection(toNodeId(wsPeerDescriptor2)))
await waitForCondition(() => connectionManager2.hasConnection(toNodeId(wsPeerDescriptor1)))
await until(() => connectionManager1.hasConnection(toNodeId(wsPeerDescriptor2)))
await until(() => connectionManager2.hasConnection(toNodeId(wsPeerDescriptor1)))
})
})

Expand Down Expand Up @@ -309,8 +309,8 @@ describe('SimultaneousConnections', () => {
connectionManager2.send(msg2)
])

await waitForCondition(() => connectionManager1.hasConnection(toNodeId(wrtcPeerDescriptor2)))
await waitForCondition(() => connectionManager2.hasConnection(toNodeId(wrtcPeerDescriptor1)))
await until(() => connectionManager1.hasConnection(toNodeId(wrtcPeerDescriptor2)))
await until(() => connectionManager2.hasConnection(toNodeId(wrtcPeerDescriptor1)))
})
})

Expand Down
Loading