tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

request-keepalive-quota.html (5172B)


      1 <!doctype html>
      2 <html>
      3    <head>
      4        <meta charset="utf-8">
      5        <title>Request Keepalive Quota Tests</title>
      6        <meta name="timeout" content="long">
      7        <meta name="help" href="https://fetch.spec.whatwg.org/#request">
      8        <meta name="help" href="https://fetch.spec.whatwg.org/#body-mixin">
      9        <meta name="author" title="Microsoft Edge" href="https://www.microsoft.com">
     10        <meta name="variant" content="?include=fast">
     11        <meta name="variant" content="?include=slow-1">
     12        <meta name="variant" content="?include=slow-2">
     13        <meta name="variant" content="?include=slow-3">
     14        <script src="/resources/testharness.js"></script>
     15        <script src="/resources/testharnessreport.js"></script>
     16        <script src="/common/subset-tests-by-key.js"></script>
     17    </head>
     18    <body>
     19        <script>
     20            'use strict';
     21 
     22            // We want to ensure that our keepalive requests hang slightly before completing so we can validate
     23            // the effects of a rolling quota. To do this we will utilize trickle.py with a 1s delay. This should
     24            // prevent any of the Fetch's from finishing in this window.
     25            const trickleURL = '../resources/trickle.py?count=1&ms=';
     26            const noDelay = 0;
     27            const standardDelay = 1000;
     28            function wait(ms) {
     29                return new Promise(resolve => step_timeout(resolve, ms));
     30            }
     31 
     32            // We should expect 64KiB of rolling quota for any type of keep-alive request sent.
     33            const expectedQuota = 65536;
     34 
     35            function fetchKeepAliveRequest(delay, bodySize) {
     36                // Create a body of the specified size that's filled with *'s
     37                const body = '*'.repeat(bodySize);
     38                return fetch(trickleURL + delay, {keepalive: true, body, method: 'POST'}).then(res => {
     39                    return res.text();
     40                }).then(() => {
     41                    return wait(1);
     42                });
     43            }
     44 
     45            // Test 1 Byte
     46            subsetTestByKey("fast", promise_test, function(test) {
     47                return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
     48            }, 'A Keep-Alive fetch() with a small body should succeed.');
     49 
     50            // Test Quota full limit
     51            subsetTestByKey("fast", promise_test, function(test) {
     52                return fetchKeepAliveRequest(noDelay, expectedQuota /* bodySize */);
     53            }, 'A Keep-Alive fetch() with a body at the Quota Limit should succeed.');
     54 
     55            // Test Quota + 1 Byte
     56            subsetTestByKey("fast", promise_test, function(test) {
     57                return promise_rejects_js(test, TypeError, fetchKeepAliveRequest(noDelay, expectedQuota + 1));
     58            }, 'A Keep-Alive fetch() with a body over the Quota Limit should reject.');
     59 
     60            // Test the Quota becomes available upon promise completion.
     61            subsetTestByKey("slow-1", promise_test, function (test) {
     62                // Fill our Quota then try to send a second fetch.
     63                return fetchKeepAliveRequest(standardDelay, expectedQuota).then(() => {
     64                    // Now validate that we can send another Keep-Alive fetch for the full size of the quota.
     65                    return fetchKeepAliveRequest(noDelay, expectedQuota);
     66                });
     67            }, 'A Keep-Alive fetch() should return its allocated Quota upon promise resolution.');
     68 
     69            // Ensure only the correct amount of Quota becomes available when a fetch completes.
     70            subsetTestByKey("slow-2", promise_test, function(test) {
     71                // Create a fetch that uses all but 1 Byte of the Quota and runs for 2x as long as the other requests.
     72                const first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
     73 
     74                // Now create a single Byte request that will complete quicker.
     75                const second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
     76                    // We shouldn't be able to create a 2 Byte request right now as only 1 Byte should have freed up.
     77                    return promise_rejects_js(test, TypeError, fetchKeepAliveRequest(noDelay, 2 /* bodySize */));
     78                }).then(() => {
     79                    // Now validate that we can send another Keep-Alive fetch for just 1 Byte.
     80                    return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
     81                });
     82 
     83                return Promise.all([first, second]);
     84            }, 'A Keep-Alive fetch() should return only its allocated Quota upon promise resolution.');
     85 
     86            // Test rejecting a fetch() after the quota is used up.
     87            subsetTestByKey("slow-3", promise_test, function (test) {
     88                // Fill our Quota then try to send a second fetch.
     89                const p = fetchKeepAliveRequest(standardDelay, expectedQuota);
     90 
     91                const q = promise_rejects_js(test, TypeError, fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
     92                return Promise.all([p, q]);
     93            }, 'A Keep-Alive fetch() should not be allowed if the Quota is used up.');
     94 
     95        </script>
     96    </body>
     97 </html>