<!DOCTYPE html>
<html>
    <head>
        <script src="../resources/js-test-pre.js"></script>
    </head>

    <body>
        <div id="description"></div>
        <div id="console"></div>

        <script>
            description("Basic tests for MediaStreamAudioSourceNode API.");

            let context;
            let stream;
            let finished = false;
            const numberOfOutputChannels = 2;
            const numberOfInputChannels = 2;
            const bufferSize = 512;

            function processAudioData(event) 
            {
                if (finished)
                    return;

                if (event.inputBuffer.numberOfChannels != numberOfInputChannels)
                    testFailed(`numberOfInputChannels doesn't match: have ${event.inputBuffer.numberOfChannels}, expect ${numberOfInputChannels}!`);

                if (event.outputBuffer.numberOfChannels != numberOfOutputChannels)
                    testFailed(`numberOfOutputChannels doesn't match: have ${event.outputBuffer.numberOfChannels}, expect ${numberOfOutputChannels}!`);

                stream.getAudioTracks()[0].stop();
                testPassed("onaudioprocess was called");
                finishJSTest();
                finished = true;
            }

            function gotStream(s)
            {
                stream = s;
                testPassed('{audio:true} generated stream');
                shouldBe('stream.getAudioTracks().length', '1');
                shouldBe('stream.getVideoTracks().length', '0');

                context = new webkitAudioContext();

                // Create an AudioNode from the stream.
                let mediaStreamSource = context.createMediaStreamSource(stream);

                // Check number of inputs and outputs.
                if (mediaStreamSource.numberOfInputs == 0)
                    testPassed("Source AudioNode has no inputs.");
                else
                    testFailed("Source AudioNode should not have inputs.");

                if (mediaStreamSource.numberOfOutputs == 1)
                    testPassed("Source AudioNode has one output.");
                else
                    testFailed("Source AudioNode should have one output.");

                // Try calling connect() method with illegal values.
                try {
                    mediaStreamSource.connect(0, 0, 0);
                    testFailed("connect() exception should be thrown for illegal destination AudioNode.");
                } catch(err) {
                    testPassed(`connect() exception {"${err.name}", "${err.message}"} thrown for illegal destination AudioNode`);
                }

                try {
                    mediaStreamSource.connect(context.destination, 5, 0);
                    testFailed("connect() exception should be thrown for illegal output index.");
                } catch(err) {
                    testPassed(`connect() exception {"${err.name}", "${err.message}"} thrown for illegal output index`);
                }

                try {
                    mediaStreamSource.connect(context.destination, 0, 5);
                    testFailed("connect() exception should be thrown for illegal input index.");
                } catch(err) {
                    testPassed(`connect() exception {"${err.name}", "${err.message}"} thrown for illegal input index`);
                }

                // Try calling connect() with legal values.
                try {
                    mediaStreamSource.connect(context.destination, 0, 0);
                    testPassed("mediaStreamSource.connect(context.destination) succeeded.");
                } catch(err) {
                    testFailed(`mediaStreamSource.connect(context.destination) failed with "${err.name}": "${err.message}"`);
                }

                let scriptProcessorNode = context.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels);
                scriptProcessorNode.onaudioprocess = processAudioData;

                mediaStreamSource.connect(scriptProcessorNode);
                scriptProcessorNode.connect(context.destination);
            }

            if (window.testRunner)
                testRunner.setUserMediaPermission(true);

            navigator.mediaDevices.getUserMedia({audio:true})
                .then(stream => gotStream(stream))
                .catch(function(err) {
                    testFailed(`mediaDevices.getUserMedia() failed with "${err.name}": "${err.message}"`);
                    finishJSTest();
                });

            window.jsTestIsAsync = true;
            window.successfullyParsed = true;
        </script>
        <script src="../resources/js-test-post.js"></script>

    </body>
</html>
