Skip to content

WebCryptoAPI: Test whether a task is scheduled to resolve/reject promises #54144

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

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
50 changes: 37 additions & 13 deletions WebCryptoAPI/digest/digest.https.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,48 +51,64 @@
var mixedCase = upCase.substr(0, 1) + downCase.substr(1);

promise_test(function(test) {
var promise = subtle.digest({name: upCase}, sourceData[size])
let microtaskTriggered = false;
let promise = subtle.digest({name: upCase}, sourceData[size])
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, digestedData[alg][size]), "digest() yielded expected result for " + alg + ":" + size);
}, function(err) {
assert_unreached("digest() threw an error for " + alg + ":" + size + " - " + err.message);
});

Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, upCase + " with " + size + " source data");

promise_test(function(test) {
var promise = subtle.digest({name: downCase}, sourceData[size])
let microtaskTriggered = false;
let promise = subtle.digest({name: downCase}, sourceData[size])
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, digestedData[alg][size]), "digest() yielded expected result for " + alg + ":" + size);
}, function(err) {
assert_unreached("digest() threw an error for " + alg + ":" + size + " - " + err.message);
});

Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, downCase + " with " + size + " source data");

promise_test(function(test) {
var promise = subtle.digest({name: mixedCase}, sourceData[size])
let microtaskTriggered = false;
let promise = subtle.digest({name: mixedCase}, sourceData[size])
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, digestedData[alg][size]), "digest() yielded expected result for " + alg + ":" + size);
}, function(err) {
assert_unreached("digest() threw an error for " + alg + ":" + size + " - " + err.message);
});

Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, mixedCase + " with " + size + " source data");

promise_test(function(test) {
var copiedBuffer = copyBuffer(sourceData[size]);
var promise = subtle.digest({name: upCase}, copiedBuffer)
let copiedBuffer = copyBuffer(sourceData[size]);
let microtaskTriggered = false;
let promise = subtle.digest({name: upCase}, copiedBuffer)
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, digestedData[alg][size]), "digest() yielded expected result for " + alg + ":" + size);
}, function(err) {
assert_unreached("digest() threw an error for " + alg + ":" + size + " - " + err.message);
});

copiedBuffer[0] = 255 - copiedBuffer;
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, upCase + " with " + size + " source data and altered buffer after call");

Expand All @@ -105,13 +121,17 @@
badNames.forEach(function(badName) {

promise_test(function(test) {
var promise = subtle.digest({name: badName}, sourceData[size])
let microtaskTriggered = false;
let promise = subtle.digest({name: badName}, sourceData[size])
.then(function(result) {
assert_unreached("digest() should not have worked for " + badName + ":" + size);
}, function(err) {
assert_false(microtaskTriggered, "promise rejected too late");
assert_equals(err.name, "NotSupportedError", "Bad algorithm name should cause NotSupportedError")
});

Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, badName + " with " + size);

Expand All @@ -121,13 +141,17 @@
// Call digest() with empty algorithm object
Object.keys(sourceData).forEach(function(size) {
promise_test(function(test) {
var promise = subtle.digest({}, sourceData[size])
let microtaskTriggered = false;
let promise = subtle.digest({}, sourceData[size])
.then(function(result) {
assert_unreached("digest() with missing algorithm name should have thrown a TypeError");
}, function(err) {
assert_false(microtaskTriggered, "promise rejected too late");
assert_equals(err.name, "TypeError", "Missing algorithm name should cause TypeError")
});

Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, "empty algorithm object with " + size);
});
Expand Down
16 changes: 14 additions & 2 deletions WebCryptoAPI/encrypt_decrypt/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ function run_test() {
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
.then(function(vector) {
promise_test(function(test) {
return subtle.encrypt(vector.algorithm, vector.key, vector.plaintext)
let microtaskTriggered = false;
let promise = subtle.encrypt(vector.algorithm, vector.key, vector.plaintext)
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, vector.result), "Should return expected result");
}, function(err) {
assert_unreached("encrypt error for test " + vector.name + ": " + err.message);
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, vector.name);
}, function(err) {
// We need a failed test if the importVectorKey operation fails, so
Expand Down Expand Up @@ -66,12 +72,18 @@ function run_test() {
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
.then(function(vector) {
promise_test(function(test) {
return subtle.decrypt(vector.algorithm, vector.key, vector.result)
let microtaskTriggered = false;
let promise = subtle.decrypt(vector.algorithm, vector.key, vector.result)
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(result, vector.plaintext), "Should return expected result");
}, function(err) {
assert_unreached("decrypt error for test " + vector.name + ": " + err.message);
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, vector.name + " decryption");
}, function(err) {
// We need a failed test if the importVectorKey operation fails, so
Expand Down
17 changes: 15 additions & 2 deletions WebCryptoAPI/encrypt_decrypt/rsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ function run_test() {
}

promise_test(function(test) {
return subtle.decrypt(vector.algorithm, vector.privateKey, vector.ciphertext)
let microtaskTriggered = false;
let promise = subtle.decrypt(vector.algorithm, vector.privateKey, vector.ciphertext)
.then(function(plaintext) {
assert_true(microtaskTriggered, "promise resolved too early");
assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works"));
}, function(err) {
assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'");
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, vector.name + " decryption");

}, function(err) {
Expand Down Expand Up @@ -175,8 +181,11 @@ function run_test() {
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
.then(function(vectors) {
promise_test(function(test) {
return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext)
let microtaskTriggered = false;
let promise = subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext)
.then(function(ciphertext) {
assert_true(microtaskTriggered, "promise resolved too early");

assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length");

// Can we get the original plaintext back via decrypt?
Expand All @@ -199,6 +208,10 @@ function run_test() {
}, function(err) {
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, vector.name);

}, function(err) {
Expand Down
14 changes: 13 additions & 1 deletion WebCryptoAPI/generateKey/failures.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,28 @@ function run_test(algorithmNames) {
// or a string, tested against the error name.
function testError(algorithm, extractable, usages, expectedError, testTag) {
promise_test(function(test) {
return crypto.subtle.generateKey(algorithm, extractable, usages)
let microtaskTriggered = false;
let promise = crypto.subtle.generateKey(algorithm, extractable, usages)
.then(function(result) {
assert_unreached("Operation succeeded, but should not have");
}, function(err) {
if (testTag === "Empty usages" || testTag === "Bad usages") {
// Error checked by the generate key operation
assert_true(microtaskTriggered, "promise rejected too early");
} else {
// Error checked by the algorithm normalization
assert_false(microtaskTriggered, "promise rejected too late");
}
if (typeof expectedError === "number") {
assert_equals(err.code, expectedError, testTag + " not supported");
} else {
assert_equals(err.name, expectedError, testTag + " not supported");
}
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, testTag + ": generateKey" + parameterString(algorithm, extractable, usages));
}

Expand Down
12 changes: 10 additions & 2 deletions WebCryptoAPI/generateKey/successes.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ function run_test(algorithmNames, slowTest) {
// testTag is a string to prepend to the test name.

promise_test(function(test) {
return subtle.generateKey(algorithm, extractable, usages)
let microtaskTriggered = false;
let promise = subtle.generateKey(algorithm, extractable, usages)
.then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");
if (resultType === "CryptoKeyPair") {
assert_goodCryptoKey(result.privateKey, algorithm, extractable, usages, "private");
assert_goodCryptoKey(result.publicKey, algorithm, true, usages, "public");
Expand Down Expand Up @@ -102,8 +104,14 @@ function run_test(algorithmNames, slowTest) {
}
}
}, function(err) {
if (err instanceof AssertionError)
throw err;
assert_unreached("exportKey threw an unexpected error: " + err.toString());
})
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, testTag + ": generateKey" + parameterString(algorithm, extractable, usages));
}

Expand Down
18 changes: 16 additions & 2 deletions WebCryptoAPI/import_export/ec_importKey.https.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,22 @@
[format] = format.split("_compressed");
}
promise_test(function(test) {
return subtle.importKey(format, keyData, algorithm, extractable, usages).
let microtaskTriggered = false;
let promise = subtle.importKey(format, keyData, algorithm, extractable, usages).
then(function(key) {
assert_true(microtaskTriggered, "promise resolved too early");

assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object");
assert_goodCryptoKey(key, algorithm, extractable, usages, (format === 'pkcs8' || (format === 'jwk' && keyData.d)) ? 'private' : 'public');
if (!extractable) {
return;
}

return subtle.exportKey(format, key).
microtaskTriggered = false;
let promise = subtle.exportKey(format, key).
then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");

if (format !== "jwk") {
assert_true(equalBuffers(data[format], result), "Round trip works");
} else {
Expand All @@ -131,13 +137,21 @@
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, function(err) {
if (compressed && err.name === "DataError") {
assert_implements_optional(false, "Compressed point format not supported: " + err.toString());
} else {
assert_unreached("Threw an unexpected error: " + err.toString());
}
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, "Good parameters: " + keySize.toString() + " bits " + parameterString(format, compressed, keyData, algorithm, extractable, usages));
}

Expand Down
15 changes: 14 additions & 1 deletion WebCryptoAPI/import_export/importKey_failures.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,22 @@ function run_test(algorithmNames) {
function testError(format, algorithm, keyData, keySize, usages, extractable, expectedError, testTag) {
promise_test(async() => {
let key;
let microtaskTriggered = false;
try {
key = await subtle.importKey(format, keyData, algorithm, extractable, usages);
let promise = subtle.importKey(format, keyData, algorithm, extractable, usages);
Promise.resolve().then(() => {
microtaskTriggered = true;
});
key = await promise;
} catch(err) {
if (testTag === "Missing algorithm name") {
// Error checked by the algorithm normalization
assert_false(microtaskTriggered, "promise rejected too late");
} else {
// Error checked by the import key operation
assert_true(microtaskTriggered, "promise rejected too early");
}

let actualError = typeof expectedError === "number" ? err.code : err.name;
assert_equals(actualError, expectedError, testTag + " not supported.");
}
Expand Down
18 changes: 16 additions & 2 deletions WebCryptoAPI/import_export/okp_importKey.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,22 @@ function runTests(algorithmName) {
function testFormat(format, algorithm, keyData, keySize, usages, extractable) {
[algorithm, algorithm.name].forEach((alg) => {
promise_test(function(test) {
return subtle.importKey(format, keyData[format], alg, extractable, usages).
let microtaskTriggered = false;
let promise = subtle.importKey(format, keyData[format], alg, extractable, usages).
then(function(key) {
assert_true(microtaskTriggered, "promise resolved too early");

assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object");
assert_goodCryptoKey(key, algorithm, extractable, usages, (format === 'pkcs8' || (format === 'jwk' && keyData[format].d)) ? 'private' : 'public');
if (!extractable) {
return;
}

return subtle.exportKey(format, key).
microtaskTriggered = false;
let promise = subtle.exportKey(format, key).
then(function(result) {
assert_true(microtaskTriggered, "promise resolved too early");

if (format !== "jwk") {
assert_true(equalBuffers(keyData[format], result), "Round trip works");
} else {
Expand All @@ -60,9 +66,17 @@ function testFormat(format, algorithm, keyData, keySize, usages, extractable) {
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, function(err) {
assert_unreached("Threw an unexpected error: " + err.toString());
});
Promise.resolve().then(() => {
microtaskTriggered = true;
});
return promise;
}, "Good parameters: " + keySize.toString() + " bits " + parameterString(format, keyData[format], alg, extractable, usages));
});
}
Expand Down
Loading