<!DOCTYPE html>
<html>

<!--
Copyright 2022 The IREE Authors

Licensed under the Apache License v2.0 with LLVM Exceptions.
See https://llvm.org/LICENSE.txt for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->

<head>
  <meta charset="utf-8" />
  <title>IREE Tests</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="./IREE_Logo_Icon_Color.svg" type="image/svg+xml">

  <style>
    .test-output-container {
      font-family: monospace;
      background-color: #111122;
      color: #88EE33;
      overflow-wrap: anywhere;
    }

    .test-output {
      white-space: pre-wrap;
      display: inline;
    }

    .stderr {
      color: red;
    }

    .start-of-line {
      user-select: none;
      color: #eeeeff;
    }
  </style>

  <!-- https://getbootstrap.com/ for some webpage styling-->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</head>

<body class="bg-dark bg-opacity-10">
  <div class="container-fluid p-2" style="font-family: monospace;">
    <div>
      Test name: <span id="test-name"></span>
      <br>
      Test output:
    </div>
    <div id="test-output" class="test-output-container border border-dark shadow-sm p-3 mb-2 rounded"></div>
    <div>
      Test result: <span id="test-result"></span>
    </div>
  </div>

  <script>
    const testNameElement = document.getElementById("test-name");
    const testOutputElement = document.getElementById("test-output");
    const testResultElement = document.getElementById("test-result")

    const searchParams = new URLSearchParams(window.location.search);
    const testName = searchParams.get("testName");
    // Load test script from URL params. This is sketchy, so keep this test
    // page local. If hosting the tests somewhere, prefer to populate the list
    // of test sources statically.
    const sourceFile = searchParams.get("sourceFile");
    const workingDirectory = searchParams.get("workingDirectory");

    document.title = "IREE Tests - " + testName;
    testNameElement.innerText = testName;

    function parseListFromString(inputString) {
      // Remove opening and closing brackets.
      let listString = inputString.replace(/^\[/, '').replace(/\]$/,'');
      if (listString == "") { return []; }
      // Remove spaces after commas.
      listString = listString.replace(/\s*,\s*/g, ",");
      // Split into an array.
      return listString.split(',');
    }

    const args = parseListFromString(searchParams.get("args") || "");
    const requiredFiles = parseListFromString(searchParams.get("requiredFiles") || "");

    function handleMessageFromWorker(messageEvent) {
      const {messageType, payload} = messageEvent.data;

      function addStartOfLine() {
        const startOfLine = document.createElement("span");
        startOfLine.textContent = "> ";
        startOfLine.classList.add("start-of-line");
        testOutputElement.appendChild(startOfLine);
      }

      function addEndOfLine() {
        const endOfLine = document.createElement("br");
        testOutputElement.appendChild(endOfLine);
      }

      if (messageType == "testResult") {
        // TODO(scotttodd): do more with result (pass/fail #s for suites)
        if (payload == 0) {
          testResultElement.innerText = "PASS";
        } else {
          testResultElement.innerText = "FAIL";
        }
      } else if (messageType == "print") {
        addStartOfLine();
        const div = document.createElement("div");
        div.textContent = payload;
        div.classList.add("test-output");
        testOutputElement.appendChild(div);
        addEndOfLine();
      } else if (messageType == "printErr") {
        addStartOfLine();
        const div = document.createElement("div");
        div.textContent = payload;
        div.classList.add("test-output");
        div.classList.add("stderr");
        testOutputElement.appendChild(div);
        addEndOfLine();
      }
    }

    const testWorker = new Worker('test_worker.js', {name: 'IREE Test Worker'});
    testWorker.onmessage = handleMessageFromWorker;
    testWorker.postMessage({
      "messageType": "runTest",
      "payload": {
        "name": testName,
        "sourceFile": sourceFile,
        "workingDirectory": workingDirectory,
        "requiredFiles": requiredFiles,
        "args": args,
      },
    });
  </script>
</body>

</html>
