<!DOCTYPE html>

<!--
  To add a new check to this test:
    1. Create the test file to be loaded and place it in
       /testdata/http_cache_test_resources/. The server delays responses when
       serving files from that directory, to make a clear distinction of what's
       being loaded from the cache.
    2. Add the file name to either CACHED_ELEMENT_LOCATIONS if you expect that
       file's mime type to be cached or UNCACHED_ELEMENT_LOCATIONS if you
       expect the file to be excluded from the cache.
    3. Add a call to the window.onload function to fetch your file, making a
       call to measureLoadTime after the file has been loaded.
-->
<head>
  <title>Cobalt HTTP Cache Test</title>
  <script src="black_box_js_test_utils.js"></script>
  <script>
    var TESTDATA_LOCATION = window.location.protocol + '//'
                              + window.location.host
                              + '/testdata/http_cache_test_resources/';
    var CACHED_ELEMENT_LOCATIONS = {
      'js': TESTDATA_LOCATION + 'http_cache.js',
      'img': TESTDATA_LOCATION + 'cobalt_logo.png',
      'css': TESTDATA_LOCATION + 'http_cache.css',
    };
    var UNCACHED_ELEMENT_LOCATIONS = {
      'txt': TESTDATA_LOCATION + 'http_cache.txt',
    };
    var EXPECTED_NUMBER_OF_ELEMENTS = Object.keys(CACHED_ELEMENT_LOCATIONS).length
                                      + Object.keys(UNCACHED_ELEMENT_LOCATIONS).length;
    var loadTimes = new Map();
    var cacheSize = 0;

    let url = window.location.search.substring(1);
    let urlVars = url.split('&');
    for (var i = 0; i < urlVars.length; i++) {
      if (urlVars[i].includes('=')) {
        var param = urlVars[i].split('=');
        loadTimes.set(param[0], param[1]);
      }
    }

    var initialLoadTime = loadTimes.has('initialLoadTime') ?
      loadTimes.get('initialLoadTime') : new Date().getTime();
    var reloadUrl = 'http_cache.html?initialLoadTime=' + initialLoadTime;
    // Append the timestamp string to each resource url to force reload the
    // files the first time the page is accessed each test run. The load time
    // is recorded on the first run and passed to the second run to ensure
    // the same url is used both times.
    var timestampString = '?t=' + initialLoadTime;

    // Ensure that the cache is enabled.
    h5vcc.storage.enableCache();

    // Make sure caching quotas are configured for required resources
    const quota = 1024 * 1024 * 1; // set 1MB for each
    let quotas = h5vcc.storage.getQuota();
    // required by test
    quotas.uncompiled_js = quota;
    quotas.image = quota;
    quotas.css = quota;
    // Adjust "other" to match the total
    quotas.other = quotas.total -
      quotas.html -  quotas.css -  quotas.image - quotas.font - quotas.splash -
      quotas.uncompiled_js -  quotas.compiled_js - quotas.cache_api -
      quotas.service_worker_js;
    const response = h5vcc.storage.setQuota(quotas);
    if(!response.success) {
      console.log("Failed to set cache quotas:" + response.error)
      notReached();
    }

    // Validate the tranferSize attribute of each performance entry specified
    // in CACHED_ELEMENT_LOCATIONS and UNCACHED_ELEMENT_LOCATIONS.
    function checkTransferSizes() {
      let elementsChecked = 0;
      // https://www.w3.org/TR/resource-timing-2/#dom-performanceresourcetiming-transfersize
      // Verify that the transferSize attribute for each resource is less than
      // 300. If greater than 300, it wasn't fetched from the cache.
      for (let location in CACHED_ELEMENT_LOCATIONS) {
        elementsChecked++;
        let tranferSize = performance.getEntriesByName(CACHED_ELEMENT_LOCATIONS[location] + timestampString)[0].transferSize;
        if (tranferSize > 300) {
          console.log('Element at ' + CACHED_ELEMENT_LOCATIONS[location]
                        + ' was expected to be cached, but was loaded from the server instead.');
          notReached();
        }
      }

      for (let location in UNCACHED_ELEMENT_LOCATIONS) {
        elementsChecked++;
        let tranferSize = performance.getEntriesByName(UNCACHED_ELEMENT_LOCATIONS[location] + timestampString)[0].transferSize;
        if (tranferSize <= 300) {
          console.log('Element at ' + UNCACHED_ELEMENT_LOCATIONS[location]
                        + ' was not expected to be cached, but was loaded from the cache.');
          notReached();
        }
      }

      if (elementsChecked == (EXPECTED_NUMBER_OF_ELEMENTS)) {
        onEndTest();
      } else {
        console.log(elementsChecked + ' elements were checked, but '
                      + EXPECTED_NUMBER_OF_ELEMENTS
                      + ' elements were expected. Verify that EXPECTED_NUMBER_OF_ELEMENTS is correctly set.');
        notReached();
      }
    }

    // On first page load, measure the load time of the specified element and
    // update the reloadUrl to record the load time. Once the expected number of
    // elements is reached, reload the page.
    // On second load, measure the load time of the specified element and
    // compare it to the first load time to validate if the cache was used,
    // failing the test if the second load took longer.
    function measureLoadTime(element, initialTime) {
      cacheSize++;
      onLoadTime = new Date().getTime() - initialTime;
      if (loadTimes.has(element)) {
        console.log(element + ' first load time: ' + loadTimes.get(element));
        console.log(element + ' second load time: ' + onLoadTime);
        if (cacheSize == EXPECTED_NUMBER_OF_ELEMENTS) {
          setTimeout(() => { checkTransferSizes(); }, 500);
        }
      } else {
        reloadUrl += '&' + element + '=' + onLoadTime;
        if (cacheSize == EXPECTED_NUMBER_OF_ELEMENTS) {
          setTimeout(() => { window.location.href = reloadUrl; }, 100);
        }
      }
    }



    // Add elements after window loads. In Cobalt, adding the onload property
    // directly to an html tag doesn't execute.
    window.onload = function () {
      // text/javascript
      let initialJsTime = new Date().getTime();
      let script = document.createElement('script');
      script.onload = (event) => {
        measureLoadTime('javascript', initialJsTime);
      };
      script.onerror = () => {
        notReached();
      };
      script.src = CACHED_ELEMENT_LOCATIONS['js'] + timestampString;
      document.getElementById('js_div').appendChild(script);

      // image/png
      let initialImgTime = new Date().getTime();
      let image = document.createElement('img');
      image.onload = () => {
        measureLoadTime('image', initialImgTime);
      };
      image.onerror = (e) => {
        notReached();
      };
      image.src = CACHED_ELEMENT_LOCATIONS['img'] + timestampString;
      image.alt = 'falied to load image';
      document.getElementById('image_div').appendChild(image);

      // text/css
      let initialCssTime = new Date().getTime();
      let css = document.createElement('link');
      css.onload = () => {
        measureLoadTime('css', initialCssTime);
      };
      css.onerror = (e) => {
        notReached();
      };
      css.rel = 'stylesheet';
      css.href = CACHED_ELEMENT_LOCATIONS['css'] + timestampString;
      document.getElementById('css_div').appendChild(css);

      // text/plain
      let initialTxtTime = new Date().getTime();
      let txt = document.createElement('p');
      fetch(UNCACHED_ELEMENT_LOCATIONS['txt'] + timestampString)
        .then(response => response.text())
        .then(text => {
          txt.innerHTML = text;
          document.getElementById('txt_div').appendChild(txt);
          measureLoadTime('txt', initialTxtTime);
      });
    }

  </script>
</head>

<body>
  <h1>HTTP CACHE TEST</h1>
  <div id="js_div">
    <h2>Loading JS Script</h2>
  </div>
  <div id="image_div">
    <h2>Loading image file (png)</h2>
  </div>
  <div id="css_div">
    <h2>Loading CSS file</h2>
  </div>
  <div id="txt_div">
    <h2>Loading txt file</h2>
  </div>
</body>
