(wasm) webdriver-based tests for JS/TS apis, update README

This commit is contained in:
Brandon Vandegrift
2023-09-06 22:13:05 -04:00
parent fa13f95a10
commit 40a1c9933c
17 changed files with 10328 additions and 222 deletions

View File

@@ -0,0 +1,99 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { VeilidTableDB, veilidClient } from 'veilid-wasm';
import { marshall, unmarshall } from './utils/marshalling-utils';
const TABLE_NAME = 'some-table';
const TABLE_COLS = 1;
describe('VeilidTable', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should open and close a table', async () => {
const table = new VeilidTableDB(TABLE_NAME, TABLE_COLS);
await table.openTable();
const keys = await table.getKeys(0);
expect(keys.length).toBe(0);
table.free();
});
describe('table operations', () => {
let table: VeilidTableDB;
before('create table', async () => {
table = new VeilidTableDB(TABLE_NAME, TABLE_COLS);
await table.openTable();
});
after('free table', async () => {
table.free();
});
it('should have no keys', async () => {
const keys = await table.getKeys(0);
expect(keys.length).toBe(0);
});
describe('store/load', () => {
const key = 'test-key with unicode 🚀';
const value = 'test value with unicode 🚀';
it('should store value', async () => {
await table.store(0, marshall(key), marshall(value));
});
it('should load value', async () => {
const storedValue = await table.load(0, marshall(key));
expect(storedValue).toBeDefined();
expect(unmarshall(storedValue!)).toBe(value);
});
it('should have key in list of keys', async () => {
const keys = await table.getKeys(0);
const decodedKeys = keys.map(unmarshall);
expect(decodedKeys).toEqual([key]);
});
});
describe('transactions', () => {
it('should commit a transaction', async () => {
let transaction = await table.createTransaction();
const key = 'tranaction-key🔥';
const first = 'first🅱';
const second = 'second✔';
const third = 'third📢';
transaction.store(0, marshall(key), marshall(first));
transaction.store(0, marshall(key), marshall(second));
transaction.store(0, marshall(key), marshall(third));
await transaction.commit();
const storedValue = await table.load(0, marshall(key));
expect(storedValue).toBeDefined();
expect(unmarshall(storedValue!)).toBe(third);
transaction.free();
});
});
});
});

View File

@@ -0,0 +1,45 @@
// TextEncoder/TextDecoder are used to solve for "The Unicode Problem" https://stackoverflow.com/a/30106551
export function marshall(data: string) {
const byteString = bytesToString(new TextEncoder().encode(data));
return base64UrlEncode(byteString);
}
export function unmarshall(b64: string) {
const byteString = base64UrlDecode(b64);
return new TextDecoder().decode(stringToBytes(byteString));
}
function base64UrlEncode(data: string) {
return removeBase64Padding(btoa(data));
}
function base64UrlDecode(b64: string) {
return atob(addBase64Padding(b64));
}
function removeBase64Padding(b64: string) {
// URL encode characters, and remove `=` padding.
return b64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
function addBase64Padding(b64: string) {
// URL decode characters
b64 = b64.replace(/-/g, '+').replace(/_/g, '/');
// Add base64 padding characters (`=`)
const rem = b64.length % 4;
if (rem === 2) {
return `${b64}==`;
} else if (rem === 3) {
return `${b64}=`;
}
return b64;
}
function stringToBytes(binString: string) {
return Uint8Array.from(binString as any, (m) => (m as any).codePointAt(0));
}
function bytesToString(bytes: Uint8Array) {
return Array.from(bytes, (x: number) => String.fromCodePoint(x)).join('');
}

View File

@@ -0,0 +1,140 @@
import type { VeilidWASMConfig } from 'veilid-wasm';
export const veilidCoreInitConfig: VeilidWASMConfig = {
logging: {
api: {
enabled: true,
level: 'Debug',
},
performance: {
enabled: false,
level: 'Info',
logs_in_timings: false,
logs_in_console: false,
},
},
};
export const veilidCoreStartupConfig = {
program_name: 'veilid-wasm-test',
namespace: '',
capabilities: {
disable: [],
},
protected_store: {
allow_insecure_fallback: true,
always_use_insecure_storage: true,
directory: '',
delete: false,
device_encryption_key_password: 'some-user-secret-value',
// "new_device_encryption_key_password": "an-updated-user-secret-value"
},
table_store: {
directory: '',
delete: false,
},
block_store: {
directory: '',
delete: false,
},
network: {
connection_initial_timeout_ms: 2000,
connection_inactivity_timeout_ms: 60000,
max_connections_per_ip4: 32,
max_connections_per_ip6_prefix: 32,
max_connections_per_ip6_prefix_size: 56,
max_connection_frequency_per_min: 128,
client_whitelist_timeout_ms: 300000,
reverse_connection_receipt_time_ms: 5000,
hole_punch_receipt_time_ms: 5000,
network_key_password: '',
disable_capabilites: [],
routing_table: {
node_id: [],
node_id_secret: [],
bootstrap: ['ws://bootstrap.veilid.net:5150/ws'],
limit_over_attached: 64,
limit_fully_attached: 32,
limit_attached_strong: 16,
limit_attached_good: 8,
limit_attached_weak: 4,
},
rpc: {
concurrency: 0,
queue_size: 1024,
max_timestamp_behind_ms: 10000,
max_timestamp_ahead_ms: 10000,
timeout_ms: 5000,
max_route_hop_count: 4,
default_route_hop_count: 1,
},
dht: {
max_find_node_count: 20,
resolve_node_timeout_ms: 10000,
resolve_node_count: 1,
resolve_node_fanout: 4,
get_value_timeout_ms: 10000,
get_value_count: 3,
get_value_fanout: 4,
set_value_timeout_ms: 10000,
set_value_count: 5,
set_value_fanout: 4,
min_peer_count: 20,
min_peer_refresh_time_ms: 60000,
validate_dial_info_receipt_time_ms: 2000,
local_subkey_cache_size: 128,
local_max_subkey_cache_memory_mb: 256,
remote_subkey_cache_size: 1024,
remote_max_records: 65536,
remote_max_subkey_cache_memory_mb: 256,
remote_max_storage_space_mb: 0,
},
upnp: true,
detect_address_changes: true,
restricted_nat_retries: 0,
tls: {
certificate_path: '',
private_key_path: '',
connection_initial_timeout_ms: 2000,
},
application: {
https: {
enabled: false,
listen_address: ':5150',
path: 'app',
},
http: {
enabled: false,
listen_address: ':5150',
path: 'app',
},
},
protocol: {
udp: {
enabled: false,
socket_pool_size: 0,
listen_address: '',
},
tcp: {
connect: false,
listen: false,
max_connections: 32,
listen_address: '',
},
ws: {
connect: true,
listen: true,
max_connections: 16,
listen_address: ':5150',
path: 'ws',
},
wss: {
connect: true,
listen: false,
max_connections: 16,
listen_address: '',
path: 'ws',
},
},
},
};

View File

@@ -0,0 +1,3 @@
export const waitForMs = (milliseconds: number) => {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
};

View File

@@ -0,0 +1,59 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { VeilidState, veilidClient } from 'veilid-wasm';
import { waitForMs } from './utils/wait-utils';
describe('veilidClient', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should print version', async () => {
const version = veilidClient.versionString();
expect(typeof version).toBe('string');
expect(version.length).toBeGreaterThan(0);
});
it('should attach and detach', async () => {
await veilidClient.attach();
await waitForMs(2000);
await veilidClient.detach();
});
describe('kitchen sink', () => {
before('attach', async () => {
await veilidClient.attach();
await waitForMs(2000);
});
after('detach', () => veilidClient.detach());
let state: VeilidState;
it('should get state', async () => {
state = await veilidClient.getState();
expect(state.attachment).toBeDefined();
expect(state.config.config).toBeDefined();
expect(state.network).toBeDefined();
});
it('should call debug command', async () => {
const response = await veilidClient.debug('txtrecord');
expect(response).toBeDefined();
expect(response.length).toBeGreaterThan(0);
});
});
});

View File

@@ -0,0 +1,38 @@
import { expect } from '@wdio/globals';
import {
veilidCoreInitConfig,
veilidCoreStartupConfig,
} from './utils/veilid-config';
import { veilidClient, veilidCrypto } from 'veilid-wasm';
describe('veilidCrypto', () => {
before('veilid startup', async () => {
veilidClient.initializeCore(veilidCoreInitConfig);
await veilidClient.startupCore((_update) => {
// if (_update.kind === 'Log') {
// console.log(_update.message);
// }
}, JSON.stringify(veilidCoreStartupConfig));
});
after('veilid shutdown', async () => {
await veilidClient.shutdownCore();
});
it('should list crypto kinds', () => {
const kinds = veilidCrypto.validCryptoKinds();
const bestKind = veilidCrypto.bestCryptoKind();
expect(typeof bestKind).toBe('string');
expect(kinds.includes(bestKind)).toBe(true);
});
it('should generate key pair', async () => {
const bestKind = veilidCrypto.bestCryptoKind();
const keypair = veilidCrypto.generateKeyPair(bestKind);
expect(typeof keypair).toBe('string');
// TODO: fix TypeScript return type of generateKeyPair to return string instead of KeyPair
});
});