| OLD | NEW |
| 1 <!doctype html> | 1 <!doctype html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <script src="../../resources/testharness.js"></script> | 4 <script src="../../resources/testharness.js"></script> |
| 5 <script src="../../resources/testharnessreport.js"></script> | 5 <script src="../../resources/testharnessreport.js"></script> |
| 6 <script src="../resources/audit-util.js"></script> | 6 <script src="../resources/audit-util.js"></script> |
| 7 <script src="../resources/audio-testing.js"></script> | 7 <script src="../resources/audit.js"></script> |
| 8 <title>Test AudioParam Nominal Range Values</title> | 8 <title>Test AudioParam Nominal Range Values</title> |
| 9 </head> | 9 </head> |
| 10 | 10 |
| 11 <body> | 11 <body> |
| 12 <script> | 12 <script> |
| 13 | 13 |
| 14 // Some arbitrary sample rate for the offline context. | 14 // Some arbitrary sample rate for the offline context. |
| 15 var sampleRate = 48000; | 15 var sampleRate = 48000; |
| 16 | 16 |
| 17 // The actual offline context | 17 // The actual offline context |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 args: [new Audio()] | 216 args: [new Audio()] |
| 217 },{ | 217 },{ |
| 218 creator: "createMediaStreamDestination", | 218 creator: "createMediaStreamDestination", |
| 219 args: [] | 219 args: [] |
| 220 } | 220 } |
| 221 // Can't currently test MediaStreamSource because we're using an offline | 221 // Can't currently test MediaStreamSource because we're using an offline |
| 222 // context. | 222 // context. |
| 223 ]; | 223 ]; |
| 224 | 224 |
| 225 // Create the context so we can use it in the following test. | 225 // Create the context so we can use it in the following test. |
| 226 audit.defineTask("initialize", function (done) { | 226 audit.define("initialize", (task, should) => { |
| 227 // Just any context so that we can create the nodes. | 227 // Just any context so that we can create the nodes. |
| 228 context = new OfflineAudioContext(1, 1, sampleRate); | 228 should(() => { |
| 229 done(); | 229 context = new OfflineAudioContext(1, 1, sampleRate); |
| 230 }, "Create context for tests") |
| 231 .notThrow(); |
| 232 task.done(); |
| 230 }); | 233 }); |
| 231 | 234 |
| 232 // Create a task for each entry in testConfigs | 235 // Create a task for each entry in testConfigs |
| 233 for (let test in testConfigs) { | 236 for (let test in testConfigs) { |
| 234 var config = testConfigs[test] | 237 var config = testConfigs[test] |
| 235 audit.defineTask(config.creator, (function (c) { | 238 audit.define(config.creator, (function (c) { |
| 236 return function (done) { | 239 return (task, should) => { |
| 237 var node = context[c.creator](...c.args); | 240 var node = context[c.creator](...c.args); |
| 238 testLimits(c.creator, node, c.limits); | 241 testLimits(should, c.creator, node, c.limits); |
| 239 done(); | 242 task.done(); |
| 240 }; | 243 }; |
| 241 })(config)); | 244 })(config)); |
| 242 } | 245 } |
| 243 | 246 |
| 244 // Test the AudioListener params that were added for the automated Panner | 247 // Test the AudioListener params that were added for the automated Panner |
| 245 audit.defineTask("AudioListener", function (done) { | 248 audit.define("AudioListener", (task, should) => { |
| 246 testLimits("", context.listener, { | 249 testLimits(should, "", context.listener, { |
| 247 positionX: { | 250 positionX: { |
| 248 minValue: -mostPositiveFloat, | 251 minValue: -mostPositiveFloat, |
| 249 maxValue: mostPositiveFloat, | 252 maxValue: mostPositiveFloat, |
| 250 }, | 253 }, |
| 251 positionY: { | 254 positionY: { |
| 252 minValue: -mostPositiveFloat, | 255 minValue: -mostPositiveFloat, |
| 253 maxValue: mostPositiveFloat, | 256 maxValue: mostPositiveFloat, |
| 254 }, | 257 }, |
| 255 positionZ: { | 258 positionZ: { |
| 256 minValue: -mostPositiveFloat, | 259 minValue: -mostPositiveFloat, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 274 }, | 277 }, |
| 275 upY: { | 278 upY: { |
| 276 minValue: -mostPositiveFloat, | 279 minValue: -mostPositiveFloat, |
| 277 maxValue: mostPositiveFloat, | 280 maxValue: mostPositiveFloat, |
| 278 }, | 281 }, |
| 279 upZ: { | 282 upZ: { |
| 280 minValue: -mostPositiveFloat, | 283 minValue: -mostPositiveFloat, |
| 281 maxValue: mostPositiveFloat, | 284 maxValue: mostPositiveFloat, |
| 282 } | 285 } |
| 283 }); | 286 }); |
| 284 done(); | 287 task.done(); |
| 285 }); | 288 }); |
| 286 | 289 |
| 287 // Verify that we have tested all the create methods available on the cont
ext. | 290 // Verify that we have tested all the create methods available on the cont
ext. |
| 288 audit.defineTask("verifyTests", function (done) { | 291 audit.define("verifyTests", (task, should) => { |
| 289 var allNodes = new Set(); | 292 var allNodes = new Set(); |
| 290 // Create the set of all "create" methods from the context. | 293 // Create the set of all "create" methods from the context. |
| 291 for (var method in context) { | 294 for (var method in context) { |
| 292 if (typeof context[method] === "function" && method.substring(0, 6) ==
= "create") { | 295 if (typeof context[method] === "function" && method.substring(0, 6) ==
= "create") { |
| 293 allNodes.add(method); | 296 allNodes.add(method); |
| 294 } | 297 } |
| 295 } | 298 } |
| 296 | 299 |
| 297 // Compute the difference between the set of all create methods on the c
ontext and the set | 300 // Compute the difference between the set of all create methods on the c
ontext and the set |
| 298 // of tests that we've run. | 301 // of tests that we've run. |
| 299 var diff = new Set([...allNodes].filter(x => !testedMethods.has(x))); | 302 var diff = new Set([...allNodes].filter(x => !testedMethods.has(x))); |
| 300 | 303 |
| 301 // Can't currently test a MediaStreamSourceNode, so remove it from the d
iff set. | 304 // Can't currently test a MediaStreamSourceNode, so remove it from the d
iff set. |
| 302 diff.delete("createMediaStreamSource"); | 305 diff.delete("createMediaStreamSource"); |
| 303 | 306 |
| 304 // It's a test failure if we didn't test all of the create methods in th
e context (except | 307 // It's a test failure if we didn't test all of the create methods in th
e context (except |
| 305 // createMediaStreamSource, of course). | 308 // createMediaStreamSource, of course). |
| 306 var output = []; | 309 var output = []; |
| 307 if (diff.size) { | 310 if (diff.size) { |
| 308 for (let item of diff) | 311 for (let item of diff) |
| 309 output.push(" " + item.substring(6)); | 312 output.push(" " + item.substring(6)); |
| 310 } | 313 } |
| 311 | 314 |
| 312 Should("Number of nodes not tested", output.length === 0) | 315 should(output.length === 0, "Number of nodes not tested") |
| 313 .summarize(": 0", | 316 .message(": 0", |
| 314 ": " + output); | 317 ": " + output); |
| 315 | 318 |
| 316 done(); | 319 task.done(); |
| 317 }); | 320 }); |
| 318 | 321 |
| 319 // Simple test of a few automation methods to verify we get warnings. | 322 // Simple test of a few automation methods to verify we get warnings. |
| 320 audit.defineTask("automation", function (done) { | 323 audit.define("automation", (task, should) => { |
| 321 // Just use a DelayNode for testing because the audio param has finite l
imits. | 324 // Just use a DelayNode for testing because the audio param has finite l
imits. |
| 325 should(() => { |
| 322 var d = context.createDelay(); | 326 var d = context.createDelay(); |
| 323 | 327 |
| 324 // The console output should have the warnings that we're interested in. | 328 // The console output should have the warnings that we're interested in. |
| 325 d.delayTime.setValueAtTime(-1, 0); | 329 d.delayTime.setValueAtTime(-1, 0); |
| 326 d.delayTime.linearRampToValueAtTime(2, 1); | 330 d.delayTime.linearRampToValueAtTime(2, 1); |
| 327 d.delayTime.exponentialRampToValueAtTime(3, 2); | 331 d.delayTime.exponentialRampToValueAtTime(3, 2); |
| 328 d.delayTime.setTargetAtTime(-1, 3, .1); | 332 d.delayTime.setTargetAtTime(-1, 3, .1); |
| 329 d.delayTime.setValueCurveAtTime(Float32Array.from([.1, .2, 1.5, -1]), 4,
.1); | 333 d.delayTime.setValueCurveAtTime(Float32Array.from([.1, .2, 1.5, -1]), 4,
.1); |
| 330 done(); | 334 }, "Test automations (check console logs)") |
| 335 .notThrow(); |
| 336 task.done(); |
| 331 }); | 337 }); |
| 332 | 338 |
| 333 // All done! | 339 audit.run(); |
| 334 audit.defineTask("finish", function (done) { | |
| 335 done(); | |
| 336 }); | |
| 337 | |
| 338 audit.runTasks(); | |
| 339 | 340 |
| 340 // Is |object| an AudioParam? We determine this by checking the construct
or name. | 341 // Is |object| an AudioParam? We determine this by checking the construct
or name. |
| 341 function isAudioParam(object) { | 342 function isAudioParam(object) { |
| 342 return object && object.constructor.name === "AudioParam"; | 343 return object && object.constructor.name === "AudioParam"; |
| 343 } | 344 } |
| 344 | 345 |
| 345 // Does |limitOptions| exist and does it have valid values for the expecte
d min and max | 346 // Does |limitOptions| exist and does it have valid values for the expecte
d min and max |
| 346 // values? | 347 // values? |
| 347 function hasValidLimits(limitOptions) { | 348 function hasValidLimits(limitOptions) { |
| 348 return limitOptions && (typeof limitOptions.minValue === "number") && (t
ypeof limitOptions.maxValue === "number"); | 349 return limitOptions && (typeof limitOptions.minValue === "number") && (t
ypeof limitOptions.maxValue === "number"); |
| 349 } | 350 } |
| 350 | 351 |
| 351 // Check the min and max values for the AudioParam attribute named |paramN
ame| for the |node|. | 352 // Check the min and max values for the AudioParam attribute named |paramN
ame| for the |node|. |
| 352 // The expected limits is given by the dictionary |limits|. If some test
fails, add the name | 353 // The expected limits is given by the dictionary |limits|. If some test
fails, add the name |
| 353 // of the failed | 354 // of the failed |
| 354 function validateAudioParamLimits(node, paramName, limits) { | 355 function validateAudioParamLimits(should, node, paramName, limits) { |
| 355 var nodeName = node.constructor.name; | 356 var nodeName = node.constructor.name; |
| 356 var parameter = node[paramName]; | 357 var parameter = node[paramName]; |
| 357 var prefix = nodeName + "." + paramName; | 358 var prefix = nodeName + "." + paramName; |
| 358 | 359 |
| 359 var success = true; | 360 var success = true; |
| 360 if (hasValidLimits(limits[paramName])) { | 361 if (hasValidLimits(limits[paramName])) { |
| 361 // Verify that the min and max values for the parameter are correct. | 362 // Verify that the min and max values for the parameter are correct. |
| 362 var isCorrect = Should(prefix + ".minValue", parameter.minValue) | 363 var isCorrect = should(parameter.minValue, prefix + ".minValue") |
| 363 .beEqualTo(limits[paramName].minValue); | 364 .beEqualTo(limits[paramName].minValue); |
| 364 isCorrect = Should(prefix + ".maxValue", parameter.maxValue) | 365 isCorrect = should(parameter.maxValue, prefix + ".maxValue") |
| 365 .beEqualTo(limits[paramName].maxValue) && isCorrect; | 366 .beEqualTo(limits[paramName].maxValue) && isCorrect; |
| 366 | 367 |
| 367 // Verify that the min and max attributes are read-only | 368 // Verify that the min and max attributes are read-only |
| 368 parameter.minValue = Math.PI; | 369 parameter.minValue = Math.PI; |
| 369 var isReadOnly; | 370 var isReadOnly; |
| 370 isReadOnly = Should(prefix + ".minValue = Math.PI", parameter.minValue
) | 371 isReadOnly = should(parameter.minValue, prefix + ".minValue = Math.PI"
) |
| 371 .notBeEqualTo(Math.PI); | 372 .notBeEqualTo(Math.PI); |
| 372 | 373 |
| 373 Should(prefix + ".minValue is read-only", isReadOnly) | 374 should(isReadOnly, prefix + ".minValue is read-only") |
| 374 .beEqualTo(true); | 375 .beEqualTo(true); |
| 375 | 376 |
| 376 isCorrect = isReadOnly && isCorrect; | 377 isCorrect = isReadOnly && isCorrect; |
| 377 | 378 |
| 378 parameter.maxValue = Math.PI; | 379 parameter.maxValue = Math.PI; |
| 379 isReadOnly = Should(prefix + ".maxValue = Math.PI", parameter.maxValue
) | 380 isReadOnly = should(parameter.maxValue, |
| 381 prefix + ".maxValue = Math.PI") |
| 380 .notBeEqualTo(Math.PI); | 382 .notBeEqualTo(Math.PI); |
| 381 Should(prefix + ".maxValue is read-only", isReadOnly) | 383 should(isReadOnly, prefix + ".maxValue is read-only") |
| 382 .beEqualTo(true); | 384 .beEqualTo(true); |
| 383 | 385 |
| 384 isCorrect = isReadOnly && isCorrect; | 386 isCorrect = isReadOnly && isCorrect; |
| 385 | 387 |
| 386 // Now try to set the parameter outside the nominal range. | 388 // Now try to set the parameter outside the nominal range. |
| 387 var newValue = 2 * limits[paramName].minValue - 1; | 389 var newValue = 2 * limits[paramName].minValue - 1; |
| 388 | 390 |
| 389 var isClipped = true; | 391 var isClipped = true; |
| 390 var clippingTested = false; | 392 var clippingTested = false; |
| 391 // If the new value is beyond float the largest single-precision float
, skip the test | 393 // If the new value is beyond float the largest single-precision float
, skip the test |
| 392 // because Chrome throws an error. | 394 // because Chrome throws an error. |
| 393 if (newValue >= -mostPositiveFloat) { | 395 if (newValue >= -mostPositiveFloat) { |
| 394 parameter.value = newValue; | 396 parameter.value = newValue; |
| 395 clippingTested = true; | 397 clippingTested = true; |
| 396 isClipped = Should("Set " + prefix + ".value = " + newValue, paramet
er.value) | 398 isClipped = should(parameter.value, |
| 399 "Set " + prefix + ".value = " + newValue) |
| 397 .beEqualTo(parameter.minValue) && isClipped; | 400 .beEqualTo(parameter.minValue) && isClipped; |
| 398 } | 401 } |
| 399 | 402 |
| 400 newValue = 2 * limits[paramName].maxValue + 1; | 403 newValue = 2 * limits[paramName].maxValue + 1; |
| 401 | 404 |
| 402 if (newValue <= mostPositiveFloat) { | 405 if (newValue <= mostPositiveFloat) { |
| 403 parameter.value = newValue; | 406 parameter.value = newValue; |
| 404 clippingTested = true; | 407 clippingTested = true; |
| 405 isClipped = Should("Set " + prefix + ".value = " + newValue, paramet
er.value) | 408 isClipped = should(parameter.value, |
| 409 "Set " + prefix + ".value = " + newValue) |
| 406 .beEqualTo(parameter.maxValue) && isClipped; | 410 .beEqualTo(parameter.maxValue) && isClipped; |
| 407 | |
| 408 } | 411 } |
| 409 | 412 |
| 410 if (clippingTested) { | 413 if (clippingTested) { |
| 411 Should(prefix + "was clipped to lie within the nominal range", isCli
pped) | 414 should(isClipped, |
| 415 prefix + "was clipped to lie within the nominal range") |
| 412 .beEqualTo(true); | 416 .beEqualTo(true); |
| 413 } | 417 } |
| 414 | 418 |
| 415 isCorrect = isCorrect && isClipped; | 419 isCorrect = isCorrect && isClipped; |
| 416 | 420 |
| 417 success = isCorrect && success; | 421 success = isCorrect && success; |
| 418 } else { | 422 } else { |
| 419 // Test config didn't specify valid limits. Fail this test! | 423 // Test config didn't specify valid limits. Fail this test! |
| 420 // testFailed("Limits for " + nodeName + "." + paramName + " were not c
orrectly defined."); | 424 should(clippingTested, |
| 421 Should("Limits for " + nodeName + "." + paramName + " were correctly d
efined", clippingTested) | 425 "Limits for " + nodeName + "." + paramName + |
| 426 " were correctly defined") |
| 422 .beEqualTo(false); | 427 .beEqualTo(false); |
| 423 | 428 |
| 424 success = false; | 429 success = false; |
| 425 } | 430 } |
| 426 | 431 |
| 427 return success; | 432 return success; |
| 428 } | 433 } |
| 429 | 434 |
| 430 // Test all of the AudioParams for |node| using the expected values in |li
mits|. | 435 // Test all of the AudioParams for |node| using the expected values in |li
mits|. |
| 431 // |creatorName| is the name of the method to create the node, and is used
to keep trakc of | 436 // |creatorName| is the name of the method to create the node, and is used
to keep trakc of |
| 432 // which tests we've run. | 437 // which tests we've run. |
| 433 function testLimits(creatorName, node, limits) { | 438 function testLimits(should, creatorName, node, limits) { |
| 434 var nodeName = node.constructor.name; | 439 var nodeName = node.constructor.name; |
| 435 testedMethods.add(creatorName); | 440 testedMethods.add(creatorName); |
| 436 | 441 |
| 437 var success = true; | 442 var success = true; |
| 438 | 443 |
| 439 // List of all of the AudioParams that were tested. | 444 // List of all of the AudioParams that were tested. |
| 440 var audioParams = []; | 445 var audioParams = []; |
| 441 | 446 |
| 442 // List of AudioParams that failed the test. | 447 // List of AudioParams that failed the test. |
| 443 var incorrectParams = []; | 448 var incorrectParams = []; |
| 444 | 449 |
| 445 // Look through all of the keys for the node and extract just the AudioP
arams | 450 // Look through all of the keys for the node and extract just the AudioP
arams |
| 446 Object.keys(node.__proto__).forEach(function (paramName) { | 451 Object.keys(node.__proto__).forEach(function (paramName) { |
| 447 if (isAudioParam(node[paramName])) { | 452 if (isAudioParam(node[paramName])) { |
| 448 audioParams.push(paramName); | 453 audioParams.push(paramName); |
| 449 var isValid = validateAudioParamLimits(node, paramName, limits, inco
rrectParams); | 454 var isValid = validateAudioParamLimits(should, node, paramName, |
| 455 limits, incorrectParams); |
| 450 if (!isValid) | 456 if (!isValid) |
| 451 incorrectParams.push(paramName); | 457 incorrectParams.push(paramName); |
| 452 | 458 |
| 453 success = isValid && success; | 459 success = isValid && success; |
| 454 } | 460 } |
| 455 }); | 461 }); |
| 456 | 462 |
| 457 // Print an appropriate message depending on whether there were AudioPar
ams defined or not. | 463 // Print an appropriate message depending on whether there were AudioPar
ams defined or not. |
| 458 if (audioParams.length) { | 464 if (audioParams.length) { |
| 459 var message = "Nominal ranges for AudioParam(s) of " + node.constructo
r.name; | 465 var message = "Nominal ranges for AudioParam(s) of " + node.constructo
r.name; |
| 460 Should(message, success) | 466 should(success, message) |
| 461 .summarize("are correct", | 467 .message("are correct", |
| 462 "are incorrect for: " + + incorrectParams); | 468 "are incorrect for: " + + incorrectParams); |
| 463 return success; | 469 return success; |
| 464 } else { | 470 } else { |
| 465 Should(nodeName, !limits) | 471 should(!limits, nodeName) |
| 466 .summarize("has no AudioParams as expected", | 472 .message("has no AudioParams as expected", |
| 467 "has no AudioParams but test expected " + limits); | 473 "has no AudioParams but test expected " + limits); |
| 468 } | 474 } |
| 469 } | 475 } |
| 470 </script> | 476 </script> |
| 471 </body> | 477 </body> |
| 472 </html> | 478 </html> |
| OLD | NEW |