| <!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> |