Setup grunt/yarn etc for loki tests plus wrote first 2 simple libloki-protocol tests
This commit is contained in:
parent
94d3ae7b5d
commit
c93aff7ebe
|
@ -11,6 +11,7 @@ js/libloki.js
|
||||||
js/util_worker.js
|
js/util_worker.js
|
||||||
js/libsignal-protocol-worker.js
|
js/libsignal-protocol-worker.js
|
||||||
libtextsecure/components.js
|
libtextsecure/components.js
|
||||||
|
libloki/test/test.js
|
||||||
libtextsecure/test/test.js
|
libtextsecure/test/test.js
|
||||||
test/test.js
|
test/test.js
|
||||||
|
|
||||||
|
@ -25,4 +26,3 @@ test/blanket_mocha.js
|
||||||
|
|
||||||
# TypeScript generated files
|
# TypeScript generated files
|
||||||
ts/**/*.js
|
ts/**/*.js
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ js/libtextsecure.js
|
||||||
js/libloki.js
|
js/libloki.js
|
||||||
libtextsecure/components.js
|
libtextsecure/components.js
|
||||||
libtextsecure/test/test.js
|
libtextsecure/test/test.js
|
||||||
|
libloki/test/test.js
|
||||||
stylesheets/*.css
|
stylesheets/*.css
|
||||||
test/test.js
|
test/test.js
|
||||||
|
|
||||||
|
|
22
Gruntfile.js
22
Gruntfile.js
|
@ -91,6 +91,14 @@ module.exports = grunt => {
|
||||||
src: ['libloki/libloki-protocol.js'],
|
src: ['libloki/libloki-protocol.js'],
|
||||||
dest: 'js/libloki.js',
|
dest: 'js/libloki.js',
|
||||||
},
|
},
|
||||||
|
lokitest: {
|
||||||
|
src: [
|
||||||
|
'node_modules/mocha/mocha.js',
|
||||||
|
'node_modules/chai/chai.js',
|
||||||
|
'libloki/test/_test.js',
|
||||||
|
],
|
||||||
|
dest: 'libloki/test/test.js',
|
||||||
|
},
|
||||||
libtextsecuretest: {
|
libtextsecuretest: {
|
||||||
src: [
|
src: [
|
||||||
'node_modules/jquery/dist/jquery.js',
|
'node_modules/jquery/dist/jquery.js',
|
||||||
|
@ -355,6 +363,17 @@ module.exports = grunt => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
grunt.registerTask(
|
||||||
|
'loki-unit-tests',
|
||||||
|
'Run loki unit tests w/Electron',
|
||||||
|
function thisNeeded() {
|
||||||
|
const environment = grunt.option('env') || 'test-loki';
|
||||||
|
const done = this.async();
|
||||||
|
|
||||||
|
runTests(environment, done);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
grunt.registerMultiTask(
|
grunt.registerMultiTask(
|
||||||
'test-release',
|
'test-release',
|
||||||
'Test packaged releases',
|
'Test packaged releases',
|
||||||
|
@ -442,7 +461,8 @@ module.exports = grunt => {
|
||||||
'locale-patch',
|
'locale-patch',
|
||||||
]);
|
]);
|
||||||
grunt.registerTask('dev', ['default', 'watch']);
|
grunt.registerTask('dev', ['default', 'watch']);
|
||||||
grunt.registerTask('test', ['unit-tests', 'lib-unit-tests']);
|
grunt.registerTask('test', ['unit-tests', 'lib-unit-tests', 'loki-unit-tests']);
|
||||||
|
grunt.registerTask('test-loki', ['loki-unit-tests']);
|
||||||
grunt.registerTask('date', ['gitinfo', 'getExpireTime']);
|
grunt.registerTask('date', ['gitinfo', 'getExpireTime']);
|
||||||
grunt.registerTask('default', [
|
grunt.registerTask('default', [
|
||||||
'exec:build-protobuf',
|
'exec:build-protobuf',
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": false,
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "script"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"strict": "off",
|
||||||
|
"more/no-then": "off"
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"assert": true,
|
||||||
|
"assertEqualArrayBuffers": true,
|
||||||
|
"dcodeIO": true,
|
||||||
|
"getString": true,
|
||||||
|
"hexToArrayBuffer": true,
|
||||||
|
"MockServer": true,
|
||||||
|
"MockSocket": true,
|
||||||
|
"clearDatabase": true,
|
||||||
|
"PROTO_ROOT": true,
|
||||||
|
"stringToArrayBuffer": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* global mocha, chai, assert, Whisper */
|
||||||
|
|
||||||
|
mocha.setup('bdd');
|
||||||
|
window.assert = chai.assert;
|
||||||
|
window.PROTO_ROOT = '../../protos';
|
||||||
|
|
||||||
|
const OriginalReporter = mocha._reporter;
|
||||||
|
|
||||||
|
const SauceReporter = function Constructor(runner) {
|
||||||
|
const failedTests = [];
|
||||||
|
|
||||||
|
runner.on('end', () => {
|
||||||
|
window.mochaResults = runner.stats;
|
||||||
|
window.mochaResults.reports = failedTests;
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('fail', (test, err) => {
|
||||||
|
const flattenTitles = item => {
|
||||||
|
const titles = [];
|
||||||
|
while (item.parent.title) {
|
||||||
|
titles.push(item.parent.title);
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
item = item.parent;
|
||||||
|
}
|
||||||
|
return titles.reverse();
|
||||||
|
};
|
||||||
|
failedTests.push({
|
||||||
|
name: test.title,
|
||||||
|
result: false,
|
||||||
|
message: err.message,
|
||||||
|
stack: err.stack,
|
||||||
|
titles: flattenTitles(test),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-new
|
||||||
|
new OriginalReporter(runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
SauceReporter.prototype = OriginalReporter.prototype;
|
||||||
|
|
||||||
|
mocha.reporter(SauceReporter);
|
||||||
|
|
||||||
|
// Override the database id.
|
||||||
|
window.Whisper = window.Whisper || {};
|
||||||
|
window.Whisper.Database = window.Whisper.Database || {};
|
||||||
|
Whisper.Database.id = 'test';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* global helpers for tests
|
||||||
|
*/
|
||||||
|
window.assertEqualArrayBuffers = (ab1, ab2) => {
|
||||||
|
assert.deepEqual(new Uint8Array(ab1), new Uint8Array(ab2));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.hexToArrayBuffer = str => {
|
||||||
|
const ret = new ArrayBuffer(str.length / 2);
|
||||||
|
const array = new Uint8Array(ret);
|
||||||
|
for (let i = 0; i < str.length / 2; i += 1)
|
||||||
|
array[i] = parseInt(str.substr(i * 2, 2), 16);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.clearDatabase = async () => {
|
||||||
|
await window.Signal.Data.removeAll();
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>libloki test runner</title>
|
||||||
|
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="mocha">
|
||||||
|
</div>
|
||||||
|
<div id="tests">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="test.js"></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/test/in_memory_signal_protocol_store.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/components.js"></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/helpers.js" data-cover></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/storage.js" data-cover></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/libsignal-protocol.js"></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/protocol_wrapper.js" data-cover></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/protobufs.js" data-cover></script>
|
||||||
|
<script type="text/javascript" src="../../libtextsecure/stringview.js" data-cover></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="../libloki-protocol.js" data-cover></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="libloki-protocol_test.js"></script>
|
||||||
|
|
||||||
|
<!-- Comment out to turn off code coverage. Useful for getting real callstacks. -->
|
||||||
|
<!-- NOTE: blanket doesn't support modern syntax and will choke until we find a replacement. :0( -->
|
||||||
|
<!-- <script type="text/javascript" src="blanket_mocha.js"></script> -->
|
||||||
|
|
||||||
|
<!-- Uncomment to start tests without code coverage enabled -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
mocha.run();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* global libsignal, libloki, textsecure, StringView */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('ConversationCollection', () => {
|
||||||
|
let fallbackCipher;
|
||||||
|
let identityKey;
|
||||||
|
let testKey;
|
||||||
|
let address;
|
||||||
|
const store = textsecure.storage.protocol;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
clearDatabase();
|
||||||
|
identityKey = await libsignal.KeyHelper.generateIdentityKeyPair();
|
||||||
|
store.put('identityKey', identityKey);
|
||||||
|
const key = libsignal.crypto.getRandomBytes(32);
|
||||||
|
const pubKeyString = StringView.arrayBufferToHex(key);
|
||||||
|
address = new libsignal.SignalProtocolAddress(
|
||||||
|
pubKeyString,
|
||||||
|
1 // sourceDevice
|
||||||
|
);
|
||||||
|
testKey = {
|
||||||
|
pubKey: libsignal.crypto.getRandomBytes(33),
|
||||||
|
privKey: libsignal.crypto.getRandomBytes(32),
|
||||||
|
};
|
||||||
|
fallbackCipher = new libloki.FallBackSessionCipher(address);
|
||||||
|
textsecure.storage.put('maxPreKeyId', 0);
|
||||||
|
textsecure.storage.put('signedKeyId', 2);
|
||||||
|
await store.storeSignedPreKey(1, testKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt fallback cipher messages as friend requests', async () => {
|
||||||
|
const buffer = new ArrayBuffer(10);
|
||||||
|
const { type } = await fallbackCipher.encrypt(buffer);
|
||||||
|
assert(type === textsecure.protobuf.Envelope.Type.FRIEND_REQUEST);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should should generate a new prekey bundle for a new contact', async () => {
|
||||||
|
const pubKey = libsignal.crypto.getRandomBytes(32);
|
||||||
|
const pubKeyString = StringView.arrayBufferToHex(pubKey);
|
||||||
|
const preKeyIdBefore = textsecure.storage.get('maxPreKeyId', 1);
|
||||||
|
const newBundle = await libloki.getPreKeyBundleForNumber(pubKeyString);
|
||||||
|
const preKeyIdAfter = textsecure.storage.get('maxPreKeyId', 1);
|
||||||
|
assert.strictEqual(preKeyIdAfter, preKeyIdBefore + 1);
|
||||||
|
|
||||||
|
const testKeyArray = new Uint8Array(testKey.pubKey);
|
||||||
|
assert.isDefined(newBundle);
|
||||||
|
assert.isDefined(newBundle.identityKey);
|
||||||
|
assert.isDefined(newBundle.deviceId);
|
||||||
|
assert.isDefined(newBundle.preKeyId);
|
||||||
|
assert.isDefined(newBundle.signedKeyId);
|
||||||
|
assert.isDefined(newBundle.preKey);
|
||||||
|
assert.isDefined(newBundle.signedKey);
|
||||||
|
assert.isDefined(newBundle.signature);
|
||||||
|
const signedKeyArray = new Uint8Array(newBundle.signedKey.toArrayBuffer());
|
||||||
|
assert.strictEqual(testKeyArray.byteLength, signedKeyArray.byteLength);
|
||||||
|
for (let i = 0 ; i !== testKeyArray.byteLength ; i += 1)
|
||||||
|
assert.strictEqual(testKeyArray[i], signedKeyArray[i]);
|
||||||
|
});
|
||||||
|
});
|
|
@ -152,4 +152,16 @@ SignalProtocolStore.prototype = {
|
||||||
resolve(deviceIds);
|
resolve(deviceIds);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
async loadPreKeyForContactIdentityKeyString(contactIdentityKeyString) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const key = this.get(`25519KeypreKey${contactIdentityKeyString}`);
|
||||||
|
if (!key) resolve(undefined);
|
||||||
|
resolve({
|
||||||
|
pubKey: key.publicKey,
|
||||||
|
privKey: key.privateKey,
|
||||||
|
keyId: key.id,
|
||||||
|
recipient: key.recipient,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
14
main.js
14
main.js
|
@ -318,6 +318,10 @@ function createWindow() {
|
||||||
mainWindow.loadURL(
|
mainWindow.loadURL(
|
||||||
prepareURL([__dirname, 'libtextsecure', 'test', 'index.html'])
|
prepareURL([__dirname, 'libtextsecure', 'test', 'index.html'])
|
||||||
);
|
);
|
||||||
|
} else if (config.environment === 'test-loki') {
|
||||||
|
mainWindow.loadURL(
|
||||||
|
prepareURL([__dirname, 'libloki', 'test', 'index.html'])
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
mainWindow.loadURL(prepareURL([__dirname, 'background.html']));
|
mainWindow.loadURL(prepareURL([__dirname, 'background.html']));
|
||||||
}
|
}
|
||||||
|
@ -341,6 +345,7 @@ function createWindow() {
|
||||||
if (
|
if (
|
||||||
config.environment === 'test' ||
|
config.environment === 'test' ||
|
||||||
config.environment === 'test-lib' ||
|
config.environment === 'test-lib' ||
|
||||||
|
config.environment === 'test-loki' ||
|
||||||
(mainWindow.readyForShutdown && windowState.shouldQuit())
|
(mainWindow.readyForShutdown && windowState.shouldQuit())
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
@ -611,7 +616,11 @@ app.on('ready', async () => {
|
||||||
const userDataPath = await getRealPath(app.getPath('userData'));
|
const userDataPath = await getRealPath(app.getPath('userData'));
|
||||||
const installPath = await getRealPath(app.getAppPath());
|
const installPath = await getRealPath(app.getAppPath());
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test' && process.env.NODE_ENV !== 'test-lib') {
|
if (
|
||||||
|
process.env.NODE_ENV !== 'test' &&
|
||||||
|
process.env.NODE_ENV !== 'test-lib' &&
|
||||||
|
process.env.NODE_ENV !== 'test-loki'
|
||||||
|
) {
|
||||||
installFileHandler({
|
installFileHandler({
|
||||||
protocol: electronProtocol,
|
protocol: electronProtocol,
|
||||||
userDataPath,
|
userDataPath,
|
||||||
|
@ -777,7 +786,8 @@ app.on('window-all-closed', () => {
|
||||||
if (
|
if (
|
||||||
process.platform !== 'darwin' ||
|
process.platform !== 'darwin' ||
|
||||||
config.environment === 'test' ||
|
config.environment === 'test' ||
|
||||||
config.environment === 'test-lib'
|
config.environment === 'test-lib' ||
|
||||||
|
config.environment === 'test-loki'
|
||||||
) {
|
) {
|
||||||
app.quit();
|
app.quit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"prepare-import-build": "node prepare_import_build.js",
|
"prepare-import-build": "node prepare_import_build.js",
|
||||||
"publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh",
|
"publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh",
|
||||||
"test": "yarn test-node && yarn test-electron",
|
"test": "yarn test-node && yarn test-electron",
|
||||||
|
"test-loki": "NODE_ENV=test-loki yarn run start",
|
||||||
"test-electron": "yarn grunt test",
|
"test-electron": "yarn grunt test",
|
||||||
"test-node": "mocha --recursive test/app test/modules ts/test",
|
"test-node": "mocha --recursive test/app test/modules ts/test",
|
||||||
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test",
|
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test",
|
||||||
|
|
Loading…
Reference in New Issue