tor-browser

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

benchmark_backend_server.js (5575B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /* globals require, process, Buffer */
      8 
      9 const http = require("http");
     10 
     11 const html = `
     12 <!DOCTYPE html>
     13 <html>
     14  <head>
     15    <title>Upload/Download test</title>
     16    <style>
     17      html {
     18      font-family: neo-sans;
     19      font-weight: 700;
     20      font-size: calc(42rem / 16);
     21      }
     22      body {
     23      background: white;
     24      }
     25      section {
     26      border-radius: 1em;
     27      padding: 1em;
     28      position: absolute;
     29      top: 50%;
     30      left: 50%;
     31      margin-right: -50%;
     32      transform: translate(-50%, -50%);
     33      }
     34    </style>
     35  </head>
     36  <body>
     37    <section>
     38      Upload/Download test
     39    </section>
     40    <button id="fileUpload">Upload Test</button>
     41    <p id="upload_status"> </p>
     42    <button id="downloadBtn">Download Test</button>
     43    <p id="download_status"></p>
     44    <script>
     45      let upload_status = "";
     46      let download_status = "";
     47 
     48      function set_status(id, status) {
     49        if (id === "upload_status") {
     50          upload_status = status;
     51        } else if (id === "download_status") {
     52          download_status = status;
     53        }
     54        console.log(id + ":" + status);
     55        document.getElementById(id).innerHTML = status;
     56      }
     57 
     58      set_status("upload_status", "not_started");
     59      set_status("download_status", "not_started");
     60 
     61      const BLOB_SIZE = 8 * 1024 * 1024;
     62 
     63      // Function to generate a Blob of specified size
     64      function generateBlob(sizeInBytes) {
     65        const array = new Uint8Array(sizeInBytes).fill(0);
     66        return new Blob([array], { type: 'application/octet-stream' });
     67      }
     68 
     69      // Function to upload the entire Blob
     70      async function uploadBlob(blob) {
     71        const formData = new FormData();
     72        formData.append('blob', blob);
     73 
     74        const response = await fetch('/saveFile', {
     75          method: 'POST',
     76          body: formData,
     77        });
     78 
     79        if (!response.ok) {
     80          throw new Error("Failed to upload Blob");
     81        }
     82 
     83        return response.json();
     84      }
     85 
     86      const handleUpload = async () => {
     87        const blob = generateBlob(BLOB_SIZE);
     88        let totalBytesUploaded = 0;
     89        set_status("upload_status", "started");
     90        const startTime = performance.now();
     91        const uploadDuration = 60 * 1000;
     92        const endTime = startTime + uploadDuration;
     93 
     94        try {
     95          while (true) {
     96            const currentTime = performance.now();
     97            if (currentTime >= endTime) {
     98              break;
     99            }
    100 
    101            await uploadBlob(blob);
    102 
    103            totalBytesUploaded += blob.size;
    104            set_status("upload_status", "uploaded:" + totalBytesUploaded);
    105          }
    106 
    107          const actualEndTime = performance.now();
    108          const totalTimeSeconds = (actualEndTime - startTime) / 1000;
    109 
    110          // Calculate goodput in Mbps
    111          const goodputMbps = (totalBytesUploaded * 8) / (totalTimeSeconds * 1_000_000);
    112          set_status("upload_status", "success goodput:" + goodputMbps);
    113        } catch (error) {
    114          set_status("upload_status", "error:" + error);
    115        }
    116      };
    117 
    118      document.querySelector('#fileUpload').addEventListener('click', handleUpload);
    119 
    120      const handleDownloadTest = () => {
    121            set_status("download_status", "started");
    122            const startTime = performance.now();
    123            fetch('/downloadTest')
    124              .then(response => response.blob())
    125              .then(blob => {
    126                const endTime = performance.now();
    127                const downloadTime = endTime - startTime;
    128                set_status("download_status", "success time:" + downloadTime);
    129              })
    130              .catch(error => {
    131                console.error(error);
    132                set_download_status("error");
    133              });
    134          }
    135      document.querySelector('#downloadBtn').addEventListener('click', handleDownloadTest);
    136    </script>
    137  </body>
    138 </html>
    139 `;
    140 
    141 const server = http.createServer((req, res) => {
    142  if (req.url === "/saveFile" && req.method.toLowerCase() === "post") {
    143    let totalSize = 0;
    144    req.on("data", chunk => {
    145      totalSize += chunk.length;
    146    });
    147 
    148    req.on("end", () => {
    149      res.writeHead(200, { "Content-Type": "application/json" });
    150      res.end(JSON.stringify({ status: "success", size: totalSize }));
    151    });
    152  } else if (
    153    req.url === "/downloadTest" &&
    154    req.method.toLowerCase() === "get"
    155  ) {
    156    const contentLength = 32 * 1024 * 1024; // 32 MB
    157    res.writeHead(200, {
    158      "Content-Type": "application/octet-stream",
    159      "Content-Length": contentLength,
    160      "Content-Disposition": "attachment; filename=testfile.bin",
    161      "Cache-Control": "no-store, no-cache, must-revalidate",
    162      Pragma: "no-cache",
    163    });
    164 
    165    const chunkSize = 1024 * 1024; // 1MB chunks
    166    for (let i = 0; i < contentLength / chunkSize; i++) {
    167      const chunk = Buffer.alloc(chunkSize, "0"); // Fill the chunk with zeros
    168      res.write(chunk);
    169    }
    170    res.end();
    171  } else if (req.url === "/" && req.method.toLowerCase() === "get") {
    172    res.writeHead(200, {
    173      "Content-Type": "text/html",
    174      "Cache-Control": "no-store, no-cache, must-revalidate",
    175      Pragma: "no-cache",
    176    });
    177    res.end(html);
    178  } else {
    179    res.writeHead(404, { "Content-Type": "text/plain" });
    180    res.end("Not Found");
    181  }
    182 });
    183 
    184 server.listen(() => {
    185  console.log(`Server is running on http://localhost:${server.address().port}`);
    186 });