<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214287] trunk/Websites/perf.webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214287">214287</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-22 17:27:01 -0700 (Wed, 22 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>/api/uploaded-file should return createdAt as a POSIX timestamp
https://bugs.webkit.org/show_bug.cgi?id=169980

Rubber-stamped by Antti Koivisto.

Call Database::to_js_time on createdAt to return it as a POSIX timestamp.

* public/include/uploaded-file-helpers.php:
(format_uploaded_file): Fixed the bug.
* server-tests/api-manifest-tests.js: Renamed from api-manifest.js.
* server-tests/api-uploaded-file-tests.js: Renamed from api-uploaded-file.js. Added a test case.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicincludeuploadedfilehelpersphp">trunk/Websites/perf.webkit.org/public/include/uploaded-file-helpers.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgservertestsapimanifesttestsjs">trunk/Websites/perf.webkit.org/server-tests/api-manifest-tests.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgservertestsapiuploadedfiletestsjs">trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file-tests.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgservertestsapimanifestjs">trunk/Websites/perf.webkit.org/server-tests/api-manifest.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgservertestsapiuploadedfilejs">trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsitesperfwebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ChangeLog (214286 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2017-03-23 00:16:37 UTC (rev 214286)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2017-03-22  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        /api/uploaded-file should return createdAt as a POSIX timestamp
+        https://bugs.webkit.org/show_bug.cgi?id=169980
+
+        Rubber-stamped by Antti Koivisto.
+
+        Call Database::to_js_time on createdAt to return it as a POSIX timestamp.
+
+        * public/include/uploaded-file-helpers.php:
+        (format_uploaded_file): Fixed the bug.
+        * server-tests/api-manifest-tests.js: Renamed from api-manifest.js.
+        * server-tests/api-uploaded-file-tests.js: Renamed from api-uploaded-file.js. Added a test case.
+
+2017-03-22  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
</ins><span class="cx">         UploadedFile should support a callback for upload progress
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=169977
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicincludeuploadedfilehelpersphp"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/include/uploaded-file-helpers.php (214286 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/include/uploaded-file-helpers.php        2017-03-23 00:16:37 UTC (rev 214286)
+++ trunk/Websites/perf.webkit.org/public/include/uploaded-file-helpers.php        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -5,7 +5,7 @@
</span><span class="cx">     return array(
</span><span class="cx">         'id' =&gt; $file_row['file_id'],
</span><span class="cx">         'size' =&gt; $file_row['file_size'],
</span><del>-        'createdAt' =&gt; $file_row['file_created_at'],
</del><ins>+        'createdAt' =&gt; Database::to_js_time($file_row['file_created_at']),
</ins><span class="cx">         'mime' =&gt; $file_row['file_mime'],
</span><span class="cx">         'filename' =&gt; $file_row['file_filename'],
</span><span class="cx">         'author' =&gt; $file_row['file_author'],
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgservertestsapimanifesttestsjsfromrev214286trunkWebsitesperfwebkitorgservertestsapimanifestjs"></a>
<div class="copfile"><h4>Copied: trunk/Websites/perf.webkit.org/server-tests/api-manifest-tests.js (from rev 214286, trunk/Websites/perf.webkit.org/server-tests/api-manifest.js) (0 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/server-tests/api-manifest-tests.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/server-tests/api-manifest-tests.js        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -0,0 +1,340 @@
</span><ins>+'use strict';
+
+const assert = require('assert');
+
+require('../tools/js/v3-models.js');
+
+const MockData = require('./resources/mock-data.js');
+const TestServer = require('./resources/test-server.js');
+const prepareServerTest = require('./resources/common-operations.js').prepareServerTest;
+
+describe('/api/manifest', function () {
+    prepareServerTest(this);
+
+    it(&quot;should generate an empty manifest when database is empty&quot;, () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/manifest').then((manifest) =&gt; {
+            assert.deepEqual(Object.keys(manifest).sort(), ['all', 'bugTrackers', 'builders', 'dashboard', 'dashboards',
+                'elapsedTime', 'fileUploadSizeLimit', 'metrics', 'repositories', 'siteTitle', 'status', 'summaryPages', 'tests', 'triggerables']);
+
+            assert.equal(typeof(manifest.elapsedTime), 'number');
+            delete manifest.elapsedTime;
+
+            assert.deepStrictEqual(manifest, {
+                siteTitle: TestServer.testConfig().siteTitle,
+                all: {},
+                bugTrackers: {},
+                builders: {},
+                dashboard: {},
+                dashboards: {},
+                fileUploadSizeLimit: 2097152, // 2MB during testing.
+                metrics: {},
+                repositories: {},
+                tests: {},
+                triggerables: {},
+                summaryPages: [],
+                status: 'OK'
+            });
+        });
+    });
+
+    const bugzillaData = {id: 1, name: 'Bugzilla', bug_url: 'https://webkit.org/b/$number', new_bug_url: 'https://bugs.webkit.org/'};
+    const radarData = {id: 2, name: 'Radar'};
+
+    it(&quot;should generate manifest with bug trackers without repositories&quot;, () =&gt; {
+        return TestServer.database().insert('bug_trackers', bugzillaData).then(() =&gt; {
+            return TestServer.remoteAPI().getJSON('/api/manifest');
+        }).then((content) =&gt; {
+            assert.deepEqual(content.bugTrackers, {1: {name: 'Bugzilla', bugUrl: 'https://webkit.org/b/$number',
+                newBugUrl: 'https://bugs.webkit.org/', repositories: null}});
+
+            let manifest = Manifest._didFetchManifest(content);
+            let tracker = BugTracker.findById(1);
+            assert(tracker);
+            assert.equal(tracker.name(), 'Bugzilla');
+            assert.equal(tracker.bugUrl(123), 'https://webkit.org/b/123');
+            assert.equal(tracker.newBugUrl(), 'https://bugs.webkit.org/');
+        });
+    });
+
+    it(&quot;should generate manifest with bug trackers and repositories&quot;, () =&gt; {
+        let db = TestServer.database();
+        return Promise.all([
+            db.insert('bug_trackers', bugzillaData),
+            db.insert('bug_trackers', radarData),
+            db.insert('repositories', {id: 11, name: 'WebKit', url: 'https://trac.webkit.org/$1'}),
+            db.insert('repositories', {id: 9, name: 'OS X'}),
+            db.insert('repositories', {id: 22, name: 'iOS'}),
+            db.insert('tracker_repositories', {tracker: bugzillaData.id, repository: 11}),
+            db.insert('tracker_repositories', {tracker: radarData.id, repository: 9}),
+            db.insert('tracker_repositories', {tracker: radarData.id, repository: 22}),
+        ]).then(() =&gt; {
+            return TestServer.remoteAPI().getJSON('/api/manifest');
+        }).then((content) =&gt; {
+            let manifest = Manifest._didFetchManifest(content);
+
+            let webkit = Repository.findById(11);
+            assert(webkit);
+            assert.equal(webkit.name(), 'WebKit');
+            assert.equal(webkit.urlForRevision(123), 'https://trac.webkit.org/123');
+
+            let osx = Repository.findById(9);
+            assert(osx);
+            assert.equal(osx.name(), 'OS X');
+
+            let ios = Repository.findById(22);
+            assert(ios);
+            assert.equal(ios.name(), 'iOS');
+
+            let tracker = BugTracker.findById(1);
+            assert(tracker);
+            assert.equal(tracker.name(), 'Bugzilla');
+            assert.equal(tracker.bugUrl(123), 'https://webkit.org/b/123');
+            assert.equal(tracker.newBugUrl(), 'https://bugs.webkit.org/');
+            assert.deepEqual(tracker.repositories(), [webkit]);
+
+            tracker = BugTracker.findById(2);
+            assert(tracker);
+            assert.equal(tracker.name(), 'Radar');
+            assert.deepEqual(Repository.sortByName(tracker.repositories()), [osx, ios]);
+        });
+    });
+
+    it(&quot;should generate manifest with builders&quot;, () =&gt; {
+        let db = TestServer.database();
+        return Promise.all([
+            db.insert('builders', {id: 1, name: 'SomeBuilder', password_hash: 'a',
+                build_url: 'https://build.webkit.org/builders/$builderName/build/$buildNumber'}),
+            db.insert('builders', {id: 2, name: 'SomeOtherBuilder', password_hash: 'b'})
+        ]).then(() =&gt; {
+            return TestServer.remoteAPI().getJSON('/api/manifest');
+        }).then((content) =&gt; {
+            assert.deepEqual(content.builders, {
+                '1': {name: 'SomeBuilder', buildUrl: 'https://build.webkit.org/builders/$builderName/build/$buildNumber'},
+                '2': {name: 'SomeOtherBuilder', buildUrl: null}
+            });
+
+            let manifest = Manifest._didFetchManifest(content);
+
+            let builder = Builder.findById(1);
+            assert(builder);
+            assert.equal(builder.name(), 'SomeBuilder');
+            assert.equal(builder.urlForBuild(123), 'https://build.webkit.org/builders/SomeBuilder/build/123');
+
+            builder = Builder.findById(2);
+            assert(builder);
+            assert.equal(builder.name(), 'SomeOtherBuilder');
+            assert.equal(builder.urlForBuild(123), null);
+        });
+    });
+
+    it(&quot;should generate manifest with tests, metrics, and platforms&quot;, () =&gt; {
+        let db = TestServer.database();
+        return Promise.all([
+            db.insert('tests', {id: 1, name: 'SomeTest'}),
+            db.insert('tests', {id: 2, name: 'SomeOtherTest'}),
+            db.insert('tests', {id: 3, name: 'ChildTest', parent: 1}),
+            db.insert('tests', {id: 4, name: 'GrandChild', parent: 3}),
+            db.insert('aggregators', {id: 200, name: 'Total'}),
+            db.insert('test_metrics', {id: 5, test: 1, name: 'Time'}),
+            db.insert('test_metrics', {id: 6, test: 2, name: 'Time', aggregator: 200}),
+            db.insert('test_metrics', {id: 7, test: 2, name: 'Malloc', aggregator: 200}),
+            db.insert('test_metrics', {id: 8, test: 3, name: 'Time'}),
+            db.insert('test_metrics', {id: 9, test: 4, name: 'Time'}),
+            db.insert('platforms', {id: 23, name: 'iOS 9 iPhone 5s'}),
+            db.insert('platforms', {id: 46, name: 'Trunk Mavericks'}),
+            db.insert('test_configurations', {id: 101, metric: 5, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 102, metric: 6, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 103, metric: 7, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 104, metric: 8, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 105, metric: 9, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 106, metric: 5, platform: 23, type: 'current'}),
+            db.insert('test_configurations', {id: 107, metric: 5, platform: 23, type: 'baseline'}),
+        ]).then(() =&gt; {
+            return TestServer.remoteAPI().getJSON('/api/manifest');
+        }).then((content) =&gt; {
+            assert.deepEqual(content.tests, {
+                &quot;1&quot;: {&quot;name&quot;: &quot;SomeTest&quot;, &quot;parentId&quot;: null, &quot;url&quot;: null},
+                &quot;2&quot;: {&quot;name&quot;: &quot;SomeOtherTest&quot;, &quot;parentId&quot;: null, &quot;url&quot;: null},
+                &quot;3&quot;: {&quot;name&quot;: &quot;ChildTest&quot;, &quot;parentId&quot;: &quot;1&quot;, &quot;url&quot;: null},
+                &quot;4&quot;: {&quot;name&quot;: &quot;GrandChild&quot;, &quot;parentId&quot;: &quot;3&quot;, &quot;url&quot;: null},
+            });
+
+            assert.deepEqual(content.metrics, {
+                '5': {name: 'Time', test: '1', aggregator: null},
+                '6': {name: 'Time', test: '2', aggregator: 'Total'},
+                '7': {name: 'Malloc', test: '2', aggregator: 'Total'},
+                '8': {name: 'Time', test: '3', aggregator: null},
+                '9': {name: 'Time', test: '4', aggregator: null},
+            });
+
+            let manifest = Manifest._didFetchManifest(content);
+
+            let someTest = Test.findById(1);
+            let someTestMetric = Metric.findById(5);
+            let someOtherTest = Test.findById(2);
+            let someOtherTestTime = Metric.findById(6);
+            let someOtherTestMalloc = Metric.findById(7);
+            let childTest = Test.findById(3);
+            let childTestMetric = Metric.findById(8);
+            let grandChildTest = Test.findById(4);
+            let ios9iphone5s = Platform.findById(23);
+            let mavericks = Platform.findById(46);
+            assert(someTest);
+            assert(someTestMetric);
+            assert(someOtherTest);
+            assert(someOtherTestTime);
+            assert(someOtherTestMalloc);
+            assert(childTest);
+            assert(childTestMetric);
+            assert(grandChildTest);
+            assert(ios9iphone5s);
+            assert(mavericks);
+
+            assert.equal(mavericks.name(), 'Trunk Mavericks');
+            assert(mavericks.hasTest(someTest));
+            assert(mavericks.hasTest(someOtherTest));
+            assert(mavericks.hasTest(childTest));
+            assert(mavericks.hasTest(grandChildTest));
+            assert(mavericks.hasMetric(someTestMetric));
+            assert(mavericks.hasMetric(someOtherTestTime));
+            assert(mavericks.hasMetric(someOtherTestMalloc));
+            assert(mavericks.hasMetric(childTestMetric));
+
+            assert.equal(ios9iphone5s.name(), 'iOS 9 iPhone 5s');
+            assert(ios9iphone5s.hasTest(someTest));
+            assert(!ios9iphone5s.hasTest(someOtherTest));
+            assert(!ios9iphone5s.hasTest(childTest));
+            assert(!ios9iphone5s.hasTest(grandChildTest));
+            assert(ios9iphone5s.hasMetric(someTestMetric));
+            assert(!ios9iphone5s.hasMetric(someOtherTestTime));
+            assert(!ios9iphone5s.hasMetric(someOtherTestMalloc));
+            assert(!ios9iphone5s.hasMetric(childTestMetric));
+
+            assert.equal(someTest.name(), 'SomeTest');
+            assert.equal(someTest.parentTest(), null);
+            assert.deepEqual(someTest.path(), [someTest]);
+            assert(!someTest.onlyContainsSingleMetric());
+            assert.deepEqual(someTest.childTests(), [childTest]);
+            assert.deepEqual(someTest.metrics(), [someTestMetric]);
+
+            assert.equal(someTestMetric.name(), 'Time');
+            assert.equal(someTestMetric.aggregatorName(), null);
+            assert.equal(someTestMetric.label(), 'Time');
+            assert.deepEqual(someTestMetric.childMetrics(), childTest.metrics());
+            assert.equal(someTestMetric.fullName(), 'SomeTest : Time');
+
+            assert.equal(someOtherTest.name(), 'SomeOtherTest');
+            assert.equal(someOtherTest.parentTest(), null);
+            assert.deepEqual(someOtherTest.path(), [someOtherTest]);
+            assert(!someOtherTest.onlyContainsSingleMetric());
+            assert.deepEqual(someOtherTest.childTests(), []);
+            assert.equal(someOtherTest.metrics().length, 2);
+            assert.equal(someOtherTest.metrics()[0].name(), 'Time');
+            assert.equal(someOtherTest.metrics()[0].aggregatorName(), 'Total');
+            assert.equal(someOtherTest.metrics()[0].label(), 'Time : Total');
+            assert.equal(someOtherTest.metrics()[0].childMetrics().length, 0);
+            assert.equal(someOtherTest.metrics()[0].fullName(), 'SomeOtherTest : Time : Total');
+            assert.equal(someOtherTest.metrics()[1].name(), 'Malloc');
+            assert.equal(someOtherTest.metrics()[1].aggregatorName(), 'Total');
+            assert.equal(someOtherTest.metrics()[1].label(), 'Malloc : Total');
+            assert.equal(someOtherTest.metrics()[1].childMetrics().length, 0);
+            assert.equal(someOtherTest.metrics()[1].fullName(), 'SomeOtherTest : Malloc : Total');
+
+            assert.equal(childTest.name(), 'ChildTest');
+            assert.equal(childTest.parentTest(), someTest);
+            assert.deepEqual(childTest.path(), [someTest, childTest]);
+            assert(!childTest.onlyContainsSingleMetric());
+            assert.deepEqual(childTest.childTests(), [grandChildTest]);
+            assert.equal(childTest.metrics().length, 1);
+            assert.equal(childTest.metrics()[0].label(), 'Time');
+            assert.equal(childTest.metrics()[0].fullName(), 'SomeTest \u220B ChildTest : Time');
+
+            assert.equal(grandChildTest.name(), 'GrandChild');
+            assert.equal(grandChildTest.parentTest(), childTest);
+            assert.deepEqual(grandChildTest.path(), [someTest, childTest, grandChildTest]);
+            assert(grandChildTest.onlyContainsSingleMetric());
+            assert.deepEqual(grandChildTest.childTests(), []);
+            assert.equal(grandChildTest.metrics().length, 1);
+            assert.equal(grandChildTest.metrics()[0].label(), 'Time');
+            assert.equal(grandChildTest.metrics()[0].fullName(), 'SomeTest \u220B ChildTest \u220B GrandChild : Time');
+        });
+    });
+
+    it(&quot;should generate manifest with triggerables&quot;, () =&gt; {
+        let db = TestServer.database();
+        return Promise.all([
+            db.insert('repositories', {id: 11, name: 'WebKit', url: 'https://trac.webkit.org/$1'}),
+            db.insert('repositories', {id: 9, name: 'OS X'}),
+            db.insert('repositories', {id: 101, name: 'WebKit', owner: 9, url: 'https://trac.webkit.org/$1'}),
+            db.insert('build_triggerables', {id: 200, name: 'build.webkit.org'}),
+            db.insert('build_triggerables', {id: 201, name: 'ios-build.webkit.org'}),
+            db.insert('tests', {id: 1, name: 'SomeTest'}),
+            db.insert('tests', {id: 2, name: 'SomeOtherTest'}),
+            db.insert('tests', {id: 3, name: 'ChildTest', parent: 1}),
+            db.insert('platforms', {id: 23, name: 'iOS 9 iPhone 5s'}),
+            db.insert('platforms', {id: 46, name: 'Trunk Mavericks'}),
+            db.insert('test_metrics', {id: 5, test: 1, name: 'Time'}),
+            db.insert('test_metrics', {id: 8, test: 2, name: 'FrameRate'}),
+            db.insert('test_metrics', {id: 9, test: 3, name: 'Time'}),
+            db.insert('test_configurations', {id: 101, metric: 5, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 102, metric: 8, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 103, metric: 9, platform: 46, type: 'current'}),
+            db.insert('test_configurations', {id: 104, metric: 5, platform: 23, type: 'current'}),
+            db.insert('test_configurations', {id: 105, metric: 8, platform: 23, type: 'current'}),
+            db.insert('test_configurations', {id: 106, metric: 9, platform: 23, type: 'current'}),
+            db.insert('triggerable_repositories', {triggerable: 200, repository: 11}),
+            db.insert('triggerable_repositories', {triggerable: 201, repository: 11}),
+            db.insert('triggerable_configurations', {triggerable: 200, test: 1, platform: 46}),
+            db.insert('triggerable_configurations', {triggerable: 200, test: 2, platform: 46}),
+            db.insert('triggerable_configurations', {triggerable: 201, test: 1, platform: 23}),
+            db.insert('triggerable_configurations', {triggerable: 201, test: 2, platform: 23}),
+        ]).then(() =&gt; {
+            return Manifest.fetch();
+        }).then(() =&gt; {
+            let webkit = Repository.findById(11);
+            assert.equal(webkit.name(), 'WebKit');
+            assert.equal(webkit.urlForRevision(123), 'https://trac.webkit.org/123');
+
+            let osWebkit1 = Repository.findById(101);
+            assert.equal(osWebkit1.name(), 'WebKit');
+            assert.equal(osWebkit1.owner(), 9);
+            assert.equal(osWebkit1.urlForRevision(123), 'https://trac.webkit.org/123');
+
+            let osx = Repository.findById(9);
+            assert.equal(osx.name(), 'OS X');
+
+            let someTest = Test.findById(1);
+            assert.equal(someTest.name(), 'SomeTest');
+
+            let someOtherTest = Test.findById(2);
+            assert.equal(someOtherTest.name(), 'SomeOtherTest');
+
+            let childTest = Test.findById(3);
+            assert.equal(childTest.name(), 'ChildTest');
+
+            let ios9iphone5s = Platform.findById(23);
+            assert.equal(ios9iphone5s.name(), 'iOS 9 iPhone 5s');
+
+            let mavericks = Platform.findById(46);
+            assert.equal(mavericks.name(), 'Trunk Mavericks');
+
+            assert.equal(Triggerable.all().length, 2);
+
+            let osxTriggerable = Triggerable.findByTestConfiguration(someTest, mavericks);
+            assert.equal(osxTriggerable.name(), 'build.webkit.org');
+            assert.deepEqual(osxTriggerable.acceptedRepositories(), [webkit]);
+
+            assert.equal(Triggerable.findByTestConfiguration(someOtherTest, mavericks), osxTriggerable);
+            assert.equal(Triggerable.findByTestConfiguration(childTest, mavericks), osxTriggerable);
+
+            let iosTriggerable = Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s);
+            assert.notEqual(iosTriggerable, osxTriggerable);
+            assert.equal(iosTriggerable.name(), 'ios-build.webkit.org');
+            assert.deepEqual(iosTriggerable.acceptedRepositories(), [webkit]);
+
+            assert.equal(Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s), iosTriggerable);
+            assert.equal(Triggerable.findByTestConfiguration(childTest, ios9iphone5s), iosTriggerable);
+        });
+    });
+
+});
</ins></span></pre></div>
<a id="trunkWebsitesperfwebkitorgservertestsapimanifestjs"></a>
<div class="delfile"><h4>Deleted: trunk/Websites/perf.webkit.org/server-tests/api-manifest.js (214286 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/server-tests/api-manifest.js        2017-03-23 00:16:37 UTC (rev 214286)
+++ trunk/Websites/perf.webkit.org/server-tests/api-manifest.js        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -1,340 +0,0 @@
</span><del>-'use strict';
-
-const assert = require('assert');
-
-require('../tools/js/v3-models.js');
-
-const MockData = require('./resources/mock-data.js');
-const TestServer = require('./resources/test-server.js');
-const prepareServerTest = require('./resources/common-operations.js').prepareServerTest;
-
-describe('/api/manifest', function () {
-    prepareServerTest(this);
-
-    it(&quot;should generate an empty manifest when database is empty&quot;, () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/manifest').then((manifest) =&gt; {
-            assert.deepEqual(Object.keys(manifest).sort(), ['all', 'bugTrackers', 'builders', 'dashboard', 'dashboards',
-                'elapsedTime', 'fileUploadSizeLimit', 'metrics', 'repositories', 'siteTitle', 'status', 'summaryPages', 'tests', 'triggerables']);
-
-            assert.equal(typeof(manifest.elapsedTime), 'number');
-            delete manifest.elapsedTime;
-
-            assert.deepStrictEqual(manifest, {
-                siteTitle: TestServer.testConfig().siteTitle,
-                all: {},
-                bugTrackers: {},
-                builders: {},
-                dashboard: {},
-                dashboards: {},
-                fileUploadSizeLimit: 2097152, // 2MB during testing.
-                metrics: {},
-                repositories: {},
-                tests: {},
-                triggerables: {},
-                summaryPages: [],
-                status: 'OK'
-            });
-        });
-    });
-
-    const bugzillaData = {id: 1, name: 'Bugzilla', bug_url: 'https://webkit.org/b/$number', new_bug_url: 'https://bugs.webkit.org/'};
-    const radarData = {id: 2, name: 'Radar'};
-
-    it(&quot;should generate manifest with bug trackers without repositories&quot;, () =&gt; {
-        return TestServer.database().insert('bug_trackers', bugzillaData).then(() =&gt; {
-            return TestServer.remoteAPI().getJSON('/api/manifest');
-        }).then((content) =&gt; {
-            assert.deepEqual(content.bugTrackers, {1: {name: 'Bugzilla', bugUrl: 'https://webkit.org/b/$number',
-                newBugUrl: 'https://bugs.webkit.org/', repositories: null}});
-
-            let manifest = Manifest._didFetchManifest(content);
-            let tracker = BugTracker.findById(1);
-            assert(tracker);
-            assert.equal(tracker.name(), 'Bugzilla');
-            assert.equal(tracker.bugUrl(123), 'https://webkit.org/b/123');
-            assert.equal(tracker.newBugUrl(), 'https://bugs.webkit.org/');
-        });
-    });
-
-    it(&quot;should generate manifest with bug trackers and repositories&quot;, () =&gt; {
-        let db = TestServer.database();
-        return Promise.all([
-            db.insert('bug_trackers', bugzillaData),
-            db.insert('bug_trackers', radarData),
-            db.insert('repositories', {id: 11, name: 'WebKit', url: 'https://trac.webkit.org/$1'}),
-            db.insert('repositories', {id: 9, name: 'OS X'}),
-            db.insert('repositories', {id: 22, name: 'iOS'}),
-            db.insert('tracker_repositories', {tracker: bugzillaData.id, repository: 11}),
-            db.insert('tracker_repositories', {tracker: radarData.id, repository: 9}),
-            db.insert('tracker_repositories', {tracker: radarData.id, repository: 22}),
-        ]).then(() =&gt; {
-            return TestServer.remoteAPI().getJSON('/api/manifest');
-        }).then((content) =&gt; {
-            let manifest = Manifest._didFetchManifest(content);
-
-            let webkit = Repository.findById(11);
-            assert(webkit);
-            assert.equal(webkit.name(), 'WebKit');
-            assert.equal(webkit.urlForRevision(123), 'https://trac.webkit.org/123');
-
-            let osx = Repository.findById(9);
-            assert(osx);
-            assert.equal(osx.name(), 'OS X');
-
-            let ios = Repository.findById(22);
-            assert(ios);
-            assert.equal(ios.name(), 'iOS');
-
-            let tracker = BugTracker.findById(1);
-            assert(tracker);
-            assert.equal(tracker.name(), 'Bugzilla');
-            assert.equal(tracker.bugUrl(123), 'https://webkit.org/b/123');
-            assert.equal(tracker.newBugUrl(), 'https://bugs.webkit.org/');
-            assert.deepEqual(tracker.repositories(), [webkit]);
-
-            tracker = BugTracker.findById(2);
-            assert(tracker);
-            assert.equal(tracker.name(), 'Radar');
-            assert.deepEqual(Repository.sortByName(tracker.repositories()), [osx, ios]);
-        });
-    });
-
-    it(&quot;should generate manifest with builders&quot;, () =&gt; {
-        let db = TestServer.database();
-        return Promise.all([
-            db.insert('builders', {id: 1, name: 'SomeBuilder', password_hash: 'a',
-                build_url: 'https://build.webkit.org/builders/$builderName/build/$buildNumber'}),
-            db.insert('builders', {id: 2, name: 'SomeOtherBuilder', password_hash: 'b'})
-        ]).then(() =&gt; {
-            return TestServer.remoteAPI().getJSON('/api/manifest');
-        }).then((content) =&gt; {
-            assert.deepEqual(content.builders, {
-                '1': {name: 'SomeBuilder', buildUrl: 'https://build.webkit.org/builders/$builderName/build/$buildNumber'},
-                '2': {name: 'SomeOtherBuilder', buildUrl: null}
-            });
-
-            let manifest = Manifest._didFetchManifest(content);
-
-            let builder = Builder.findById(1);
-            assert(builder);
-            assert.equal(builder.name(), 'SomeBuilder');
-            assert.equal(builder.urlForBuild(123), 'https://build.webkit.org/builders/SomeBuilder/build/123');
-
-            builder = Builder.findById(2);
-            assert(builder);
-            assert.equal(builder.name(), 'SomeOtherBuilder');
-            assert.equal(builder.urlForBuild(123), null);
-        });
-    });
-
-    it(&quot;should generate manifest with tests, metrics, and platforms&quot;, () =&gt; {
-        let db = TestServer.database();
-        return Promise.all([
-            db.insert('tests', {id: 1, name: 'SomeTest'}),
-            db.insert('tests', {id: 2, name: 'SomeOtherTest'}),
-            db.insert('tests', {id: 3, name: 'ChildTest', parent: 1}),
-            db.insert('tests', {id: 4, name: 'GrandChild', parent: 3}),
-            db.insert('aggregators', {id: 200, name: 'Total'}),
-            db.insert('test_metrics', {id: 5, test: 1, name: 'Time'}),
-            db.insert('test_metrics', {id: 6, test: 2, name: 'Time', aggregator: 200}),
-            db.insert('test_metrics', {id: 7, test: 2, name: 'Malloc', aggregator: 200}),
-            db.insert('test_metrics', {id: 8, test: 3, name: 'Time'}),
-            db.insert('test_metrics', {id: 9, test: 4, name: 'Time'}),
-            db.insert('platforms', {id: 23, name: 'iOS 9 iPhone 5s'}),
-            db.insert('platforms', {id: 46, name: 'Trunk Mavericks'}),
-            db.insert('test_configurations', {id: 101, metric: 5, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 102, metric: 6, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 103, metric: 7, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 104, metric: 8, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 105, metric: 9, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 106, metric: 5, platform: 23, type: 'current'}),
-            db.insert('test_configurations', {id: 107, metric: 5, platform: 23, type: 'baseline'}),
-        ]).then(() =&gt; {
-            return TestServer.remoteAPI().getJSON('/api/manifest');
-        }).then((content) =&gt; {
-            assert.deepEqual(content.tests, {
-                &quot;1&quot;: {&quot;name&quot;: &quot;SomeTest&quot;, &quot;parentId&quot;: null, &quot;url&quot;: null},
-                &quot;2&quot;: {&quot;name&quot;: &quot;SomeOtherTest&quot;, &quot;parentId&quot;: null, &quot;url&quot;: null},
-                &quot;3&quot;: {&quot;name&quot;: &quot;ChildTest&quot;, &quot;parentId&quot;: &quot;1&quot;, &quot;url&quot;: null},
-                &quot;4&quot;: {&quot;name&quot;: &quot;GrandChild&quot;, &quot;parentId&quot;: &quot;3&quot;, &quot;url&quot;: null},
-            });
-
-            assert.deepEqual(content.metrics, {
-                '5': {name: 'Time', test: '1', aggregator: null},
-                '6': {name: 'Time', test: '2', aggregator: 'Total'},
-                '7': {name: 'Malloc', test: '2', aggregator: 'Total'},
-                '8': {name: 'Time', test: '3', aggregator: null},
-                '9': {name: 'Time', test: '4', aggregator: null},
-            });
-
-            let manifest = Manifest._didFetchManifest(content);
-
-            let someTest = Test.findById(1);
-            let someTestMetric = Metric.findById(5);
-            let someOtherTest = Test.findById(2);
-            let someOtherTestTime = Metric.findById(6);
-            let someOtherTestMalloc = Metric.findById(7);
-            let childTest = Test.findById(3);
-            let childTestMetric = Metric.findById(8);
-            let grandChildTest = Test.findById(4);
-            let ios9iphone5s = Platform.findById(23);
-            let mavericks = Platform.findById(46);
-            assert(someTest);
-            assert(someTestMetric);
-            assert(someOtherTest);
-            assert(someOtherTestTime);
-            assert(someOtherTestMalloc);
-            assert(childTest);
-            assert(childTestMetric);
-            assert(grandChildTest);
-            assert(ios9iphone5s);
-            assert(mavericks);
-
-            assert.equal(mavericks.name(), 'Trunk Mavericks');
-            assert(mavericks.hasTest(someTest));
-            assert(mavericks.hasTest(someOtherTest));
-            assert(mavericks.hasTest(childTest));
-            assert(mavericks.hasTest(grandChildTest));
-            assert(mavericks.hasMetric(someTestMetric));
-            assert(mavericks.hasMetric(someOtherTestTime));
-            assert(mavericks.hasMetric(someOtherTestMalloc));
-            assert(mavericks.hasMetric(childTestMetric));
-
-            assert.equal(ios9iphone5s.name(), 'iOS 9 iPhone 5s');
-            assert(ios9iphone5s.hasTest(someTest));
-            assert(!ios9iphone5s.hasTest(someOtherTest));
-            assert(!ios9iphone5s.hasTest(childTest));
-            assert(!ios9iphone5s.hasTest(grandChildTest));
-            assert(ios9iphone5s.hasMetric(someTestMetric));
-            assert(!ios9iphone5s.hasMetric(someOtherTestTime));
-            assert(!ios9iphone5s.hasMetric(someOtherTestMalloc));
-            assert(!ios9iphone5s.hasMetric(childTestMetric));
-
-            assert.equal(someTest.name(), 'SomeTest');
-            assert.equal(someTest.parentTest(), null);
-            assert.deepEqual(someTest.path(), [someTest]);
-            assert(!someTest.onlyContainsSingleMetric());
-            assert.deepEqual(someTest.childTests(), [childTest]);
-            assert.deepEqual(someTest.metrics(), [someTestMetric]);
-
-            assert.equal(someTestMetric.name(), 'Time');
-            assert.equal(someTestMetric.aggregatorName(), null);
-            assert.equal(someTestMetric.label(), 'Time');
-            assert.deepEqual(someTestMetric.childMetrics(), childTest.metrics());
-            assert.equal(someTestMetric.fullName(), 'SomeTest : Time');
-
-            assert.equal(someOtherTest.name(), 'SomeOtherTest');
-            assert.equal(someOtherTest.parentTest(), null);
-            assert.deepEqual(someOtherTest.path(), [someOtherTest]);
-            assert(!someOtherTest.onlyContainsSingleMetric());
-            assert.deepEqual(someOtherTest.childTests(), []);
-            assert.equal(someOtherTest.metrics().length, 2);
-            assert.equal(someOtherTest.metrics()[0].name(), 'Time');
-            assert.equal(someOtherTest.metrics()[0].aggregatorName(), 'Total');
-            assert.equal(someOtherTest.metrics()[0].label(), 'Time : Total');
-            assert.equal(someOtherTest.metrics()[0].childMetrics().length, 0);
-            assert.equal(someOtherTest.metrics()[0].fullName(), 'SomeOtherTest : Time : Total');
-            assert.equal(someOtherTest.metrics()[1].name(), 'Malloc');
-            assert.equal(someOtherTest.metrics()[1].aggregatorName(), 'Total');
-            assert.equal(someOtherTest.metrics()[1].label(), 'Malloc : Total');
-            assert.equal(someOtherTest.metrics()[1].childMetrics().length, 0);
-            assert.equal(someOtherTest.metrics()[1].fullName(), 'SomeOtherTest : Malloc : Total');
-
-            assert.equal(childTest.name(), 'ChildTest');
-            assert.equal(childTest.parentTest(), someTest);
-            assert.deepEqual(childTest.path(), [someTest, childTest]);
-            assert(!childTest.onlyContainsSingleMetric());
-            assert.deepEqual(childTest.childTests(), [grandChildTest]);
-            assert.equal(childTest.metrics().length, 1);
-            assert.equal(childTest.metrics()[0].label(), 'Time');
-            assert.equal(childTest.metrics()[0].fullName(), 'SomeTest \u220B ChildTest : Time');
-
-            assert.equal(grandChildTest.name(), 'GrandChild');
-            assert.equal(grandChildTest.parentTest(), childTest);
-            assert.deepEqual(grandChildTest.path(), [someTest, childTest, grandChildTest]);
-            assert(grandChildTest.onlyContainsSingleMetric());
-            assert.deepEqual(grandChildTest.childTests(), []);
-            assert.equal(grandChildTest.metrics().length, 1);
-            assert.equal(grandChildTest.metrics()[0].label(), 'Time');
-            assert.equal(grandChildTest.metrics()[0].fullName(), 'SomeTest \u220B ChildTest \u220B GrandChild : Time');
-        });
-    });
-
-    it(&quot;should generate manifest with triggerables&quot;, () =&gt; {
-        let db = TestServer.database();
-        return Promise.all([
-            db.insert('repositories', {id: 11, name: 'WebKit', url: 'https://trac.webkit.org/$1'}),
-            db.insert('repositories', {id: 9, name: 'OS X'}),
-            db.insert('repositories', {id: 101, name: 'WebKit', owner: 9, url: 'https://trac.webkit.org/$1'}),
-            db.insert('build_triggerables', {id: 200, name: 'build.webkit.org'}),
-            db.insert('build_triggerables', {id: 201, name: 'ios-build.webkit.org'}),
-            db.insert('tests', {id: 1, name: 'SomeTest'}),
-            db.insert('tests', {id: 2, name: 'SomeOtherTest'}),
-            db.insert('tests', {id: 3, name: 'ChildTest', parent: 1}),
-            db.insert('platforms', {id: 23, name: 'iOS 9 iPhone 5s'}),
-            db.insert('platforms', {id: 46, name: 'Trunk Mavericks'}),
-            db.insert('test_metrics', {id: 5, test: 1, name: 'Time'}),
-            db.insert('test_metrics', {id: 8, test: 2, name: 'FrameRate'}),
-            db.insert('test_metrics', {id: 9, test: 3, name: 'Time'}),
-            db.insert('test_configurations', {id: 101, metric: 5, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 102, metric: 8, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 103, metric: 9, platform: 46, type: 'current'}),
-            db.insert('test_configurations', {id: 104, metric: 5, platform: 23, type: 'current'}),
-            db.insert('test_configurations', {id: 105, metric: 8, platform: 23, type: 'current'}),
-            db.insert('test_configurations', {id: 106, metric: 9, platform: 23, type: 'current'}),
-            db.insert('triggerable_repositories', {triggerable: 200, repository: 11}),
-            db.insert('triggerable_repositories', {triggerable: 201, repository: 11}),
-            db.insert('triggerable_configurations', {triggerable: 200, test: 1, platform: 46}),
-            db.insert('triggerable_configurations', {triggerable: 200, test: 2, platform: 46}),
-            db.insert('triggerable_configurations', {triggerable: 201, test: 1, platform: 23}),
-            db.insert('triggerable_configurations', {triggerable: 201, test: 2, platform: 23}),
-        ]).then(() =&gt; {
-            return Manifest.fetch();
-        }).then(() =&gt; {
-            let webkit = Repository.findById(11);
-            assert.equal(webkit.name(), 'WebKit');
-            assert.equal(webkit.urlForRevision(123), 'https://trac.webkit.org/123');
-
-            let osWebkit1 = Repository.findById(101);
-            assert.equal(osWebkit1.name(), 'WebKit');
-            assert.equal(osWebkit1.owner(), 9);
-            assert.equal(osWebkit1.urlForRevision(123), 'https://trac.webkit.org/123');
-
-            let osx = Repository.findById(9);
-            assert.equal(osx.name(), 'OS X');
-
-            let someTest = Test.findById(1);
-            assert.equal(someTest.name(), 'SomeTest');
-
-            let someOtherTest = Test.findById(2);
-            assert.equal(someOtherTest.name(), 'SomeOtherTest');
-
-            let childTest = Test.findById(3);
-            assert.equal(childTest.name(), 'ChildTest');
-
-            let ios9iphone5s = Platform.findById(23);
-            assert.equal(ios9iphone5s.name(), 'iOS 9 iPhone 5s');
-
-            let mavericks = Platform.findById(46);
-            assert.equal(mavericks.name(), 'Trunk Mavericks');
-
-            assert.equal(Triggerable.all().length, 2);
-
-            let osxTriggerable = Triggerable.findByTestConfiguration(someTest, mavericks);
-            assert.equal(osxTriggerable.name(), 'build.webkit.org');
-            assert.deepEqual(osxTriggerable.acceptedRepositories(), [webkit]);
-
-            assert.equal(Triggerable.findByTestConfiguration(someOtherTest, mavericks), osxTriggerable);
-            assert.equal(Triggerable.findByTestConfiguration(childTest, mavericks), osxTriggerable);
-
-            let iosTriggerable = Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s);
-            assert.notEqual(iosTriggerable, osxTriggerable);
-            assert.equal(iosTriggerable.name(), 'ios-build.webkit.org');
-            assert.deepEqual(iosTriggerable.acceptedRepositories(), [webkit]);
-
-            assert.equal(Triggerable.findByTestConfiguration(someOtherTest, ios9iphone5s), iosTriggerable);
-            assert.equal(Triggerable.findByTestConfiguration(childTest, ios9iphone5s), iosTriggerable);
-        });
-    });
-
-});
</del></span></pre></div>
<a id="trunkWebsitesperfwebkitorgservertestsapiuploadedfiletestsjsfromrev214286trunkWebsitesperfwebkitorgservertestsapiuploadedfilejs"></a>
<div class="copfile"><h4>Copied: trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file-tests.js (from rev 214286, trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file.js) (0 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file-tests.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file-tests.js        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -0,0 +1,324 @@
</span><ins>+'use strict';
+
+require('../tools/js/v3-models.js');
+
+const assert = require('assert');
+global.FormData = require('form-data');
+
+const TestServer = require('./resources/test-server.js');
+const TemporaryFile = require('./resources/temporary-file.js').TemporaryFile;
+
+describe('/api/uploaded-file', function () {
+    this.timeout(5000);
+    TestServer.inject();
+
+    TemporaryFile.inject();
+
+    it('should return &quot;InvalidArguments&quot; when neither path nor sha256 query is set', () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/uploaded-file').then((content) =&gt; {
+            assert.equal(content['status'], 'InvalidArguments');
+            return TestServer.remoteAPI().getJSON('/api/uploaded-file/');
+        }).then((content) =&gt; {
+            assert.equal(content['status'], 'InvalidArguments');
+        });
+    });
+
+    it('should return 404 when there is no file with the specified ID', () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/uploaded-file/1').then((content) =&gt; {
+            assert(false, 'should never be reached');
+        }, (error) =&gt; {
+            assert.equal(error, 404);
+        });
+    });
+
+    it('should return 404 when the specified ID is not a valid integer', () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/uploaded-file/foo').then((content) =&gt; {
+            assert(false, 'should never be reached');
+        }, (error) =&gt; {
+            assert.equal(error, 404);
+        });
+    });
+
+    it('should return the file content matching the specified file ID', () =&gt; {
+        let uploadedFile;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            uploadedFile = response['uploadedFile'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${uploadedFile['id']}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            assert.equal(response.responseText, 'some content');
+        });
+    });
+
+    it('should return the file content with createdAt using POSIX timestamp in UTC', () =&gt; {
+        let uploadedFile;
+        const startTime = +Date.now();
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            uploadedFile = response['uploadedFile'];
+            console.assert(typeof(uploadedFile.createdAt) == 'number')
+            const createdAt = +new Date(uploadedFile.createdAt);
+            const endTime = +Date.now();
+            assert(startTime &lt;= createdAt, 'createdAt should be after the time POST request was made');
+            assert(createdAt &lt;= endTime, 'createdAt should be before the uploadedFile response had finished');
+        });
+    });
+
+    it('should return &quot;NotFound&quot; when the specified SHA256 is invalid', () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/uploaded-file/?sha256=abc').then((content) =&gt; {
+            assert.equal(content['status'], 'NotFound');
+        });
+    });
+
+    it('should return &quot;NotFound&quot; when there is no file matching the specified SHA256 ', () =&gt; {
+        return TestServer.remoteAPI().getJSON('/api/uploaded-file/?sha256=5256ec18f11624025905d057d6befb03d77b243511ac5f77ed5e0221ce6d84b5').then((content) =&gt; {
+            assert.equal(content['status'], 'NotFound');
+        });
+    });
+
+    it('should return the meta data of the file with the specified SHA256', () =&gt; {
+        let uploadedFile;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            uploadedFile = response['uploadedFile'];
+            return TestServer.remoteAPI().getJSON(`/api/uploaded-file/?sha256=${uploadedFile['sha256']}`);
+        }).then((response) =&gt; {
+            assert.deepEqual(uploadedFile, response['uploadedFile']);
+        });
+    });
+
+    it('should return &quot;NotFound&quot; when the file matching the specified SHA256 had already been deleted', () =&gt; {
+        let uploadedFile;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            uploadedFile = response['uploadedFile'];
+            const db = TestServer.database();
+            return db.connect().then(() =&gt; db.query(`UPDATE uploaded_files SET file_deleted_at = now() at time zone 'utc'`));
+        }).then(() =&gt; {
+            return TestServer.remoteAPI().getJSON(`/api/uploaded-file/?sha256=${uploadedFile['sha256']}`);
+        }).then((content) =&gt; {
+            assert.equal(content['status'], 'NotFound');
+        });
+    });
+
+
+    it('should respond with ETag, Acccept-Ranges, Content-Disposition, Content-Length, and Last-Modified headers', () =&gt; {
+        let uploadedFile;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            uploadedFile = response['uploadedFile'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${uploadedFile['id']}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            const headers = response.headers;
+
+            assert(Object.keys(headers).includes('etag'));
+            assert.equal(headers['etag'], uploadedFile['sha256']);
+
+            assert(Object.keys(headers).includes('accept-ranges'));
+            assert.equal(headers['accept-ranges'], 'bytes');
+
+            assert(Object.keys(headers).includes('content-disposition'));
+            assert.equal(headers['content-disposition'], `attachment; filename*=utf-8''some.dat`);
+
+            assert(Object.keys(headers).includes('content-length'));
+            assert.equal(headers['content-length'], uploadedFile['size']);
+
+            assert(Object.keys(headers).includes('last-modified'));
+        });
+    });
+
+    it('should respond with the same Last-Modified each time', () =&gt; {
+        let id;
+        let lastModified;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            lastModified = response.headers['last-modified'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            assert.equal(response.headers['last-modified'], lastModified);
+        });
+    });
+
+    it('should respond with Content-Range when requested after X bytes', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=5-'}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 5-11/12');
+            assert.equal(response.responseText, 'content');
+        });
+    });
+
+    it('should respond with Content-Range when requested between X-Y bytes', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=4-9'}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 4-9/12');
+            assert.equal(response.responseText, ' conte');
+        });
+    });
+
+    it('should respond with Content-Range when requested for the last X bytes', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=-4'}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 8-11/12');
+            assert.equal(response.responseText, 'tent');
+        });
+    });
+
+    it('should respond with Content-Range for the whole content when the suffix length is larger than the content', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=-100'}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 0-11/12');
+            assert.equal(response.responseText, 'some content');
+        });
+    });
+
+    it('should return 416 when the starting byte is after the file size', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=12-'}})
+                .then(() =&gt; assert(false, 'should never be reached'), (error) =&gt; assert.equal(error, 416));
+        });
+    });
+
+    it('should return 416 when the starting byte after the ending byte', () =&gt; {
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            const id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=2-1'}})
+                .then(() =&gt; assert(false, 'should never be reached'), (error) =&gt; assert.equal(error, 416));
+        });
+    });
+
+    it('should respond with Content-Range when If-Range matches the last modified date', () =&gt; {
+        let id;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            assert.equal(response.statusCode, 200);
+            assert.equal(response.responseText, 'some content');
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
+                {headers: {'Range': 'bytes = 9-10', 'If-Range': response.headers['last-modified']}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 9-10/12');
+            assert.equal(response.responseText, 'en');
+        });
+    });
+
+    it('should respond with Content-Range when If-Range matches ETag', () =&gt; {
+        let id;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            assert.equal(response.statusCode, 200);
+            assert.equal(response.responseText, 'some content');
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
+                {headers: {'Range': 'bytes = 9-10', 'If-Range': response.headers['etag']}});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], 'bytes 9-10/12');
+            assert.equal(response.responseText, 'en');
+        });
+    });
+
+    it('should return the full content when If-Range does not match the last modified date or ETag', () =&gt; {
+        let id;
+        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
+        }).then((response) =&gt; {
+            assert.equal(response.statusCode, 200);
+            assert.equal(response.responseText, 'some content');
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
+                {'Range': 'bytes = 9-10', 'If-Range': 'foo'});
+        }).then((response) =&gt; {
+            assert.equal(response.statusCode, 200);
+            assert.equal(response.responseText, 'some content');
+        });
+    });
+
+    it('should respond with Content-Range across 64KB streaming chunks', () =&gt; {
+        let id;
+        const fileSize = 256 * 1024;
+        const tokens = &quot;0123456789abcdefghijklmnopqrstuvwxyz&quot;;
+        let buffer = Buffer.allocUnsafe(fileSize);
+        for (let i = 0; i &lt; fileSize; i++)
+            buffer[i] = Math.floor(Math.random() * 256);
+        let startByte = 63 * 1024;
+        let endByte = 128 * 1024 - 1;
+
+        let responseBufferList = [];
+        const responseHandler = (response) =&gt; {
+            response.on('data', (chunk) =&gt; responseBufferList.push(chunk));
+        };
+
+        function verifyBuffer()
+        {
+            const responseBuffer = Buffer.concat(responseBufferList);
+            for (let i = 0; i &lt; endByte - startByte + 1; i++) {
+                const actual = responseBuffer[i];
+                const expected = buffer[startByte + i];
+                assert.equal(actual, expected, `The byte at index ${i} should be identical. Expected ${expected} but got ${actual}`);
+            }
+        }
+
+        return TemporaryFile.makeTemporaryFile('some.dat', buffer).then((stream) =&gt; {
+            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
+        }).then((response) =&gt; {
+            id = response['uploadedFile']['id'];
+            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
+                {headers: {'Range': `bytes = ${startByte}-${endByte}`}, responseHandler});
+        }).then((response) =&gt; {
+            const headers = response.headers;
+            assert.equal(response.statusCode, 206);
+            assert.equal(headers['content-range'], `bytes ${startByte}-${endByte}/${fileSize}`);
+            verifyBuffer();
+        });
+    });
+
+});
</ins></span></pre></div>
<a id="trunkWebsitesperfwebkitorgservertestsapiuploadedfilejs"></a>
<div class="delfile"><h4>Deleted: trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file.js (214286 => 214287)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file.js        2017-03-23 00:16:37 UTC (rev 214286)
+++ trunk/Websites/perf.webkit.org/server-tests/api-uploaded-file.js        2017-03-23 00:27:01 UTC (rev 214287)
</span><span class="lines">@@ -1,309 +0,0 @@
</span><del>-'use strict';
-
-require('../tools/js/v3-models.js');
-
-const assert = require('assert');
-global.FormData = require('form-data');
-
-const TestServer = require('./resources/test-server.js');
-const TemporaryFile = require('./resources/temporary-file.js').TemporaryFile;
-
-describe('/api/uploaded-file', function () {
-    this.timeout(5000);
-    TestServer.inject();
-
-    TemporaryFile.inject();
-
-    it('should return &quot;InvalidArguments&quot; when neither path nor sha256 query is set', () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/uploaded-file').then((content) =&gt; {
-            assert.equal(content['status'], 'InvalidArguments');
-            return TestServer.remoteAPI().getJSON('/api/uploaded-file/');
-        }).then((content) =&gt; {
-            assert.equal(content['status'], 'InvalidArguments');
-        });
-    });
-
-    it('should return 404 when there is no file with the specified ID', () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/uploaded-file/1').then((content) =&gt; {
-            assert(false, 'should never be reached');
-        }, (error) =&gt; {
-            assert.equal(error, 404);
-        });
-    });
-
-    it('should return 404 when the specified ID is not a valid integer', () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/uploaded-file/foo').then((content) =&gt; {
-            assert(false, 'should never be reached');
-        }, (error) =&gt; {
-            assert.equal(error, 404);
-        });
-    });
-
-    it('should return the file content matching the specified file ID', () =&gt; {
-        let uploadedFile;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            uploadedFile = response['uploadedFile'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${uploadedFile['id']}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            assert.equal(response.responseText, 'some content');
-        });
-    });
-
-    it('should return &quot;NotFound&quot; when the specified SHA256 is invalid', () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/uploaded-file/?sha256=abc').then((content) =&gt; {
-            assert.equal(content['status'], 'NotFound');
-        });
-    });
-
-    it('should return &quot;NotFound&quot; when there is no file matching the specified SHA256 ', () =&gt; {
-        return TestServer.remoteAPI().getJSON('/api/uploaded-file/?sha256=5256ec18f11624025905d057d6befb03d77b243511ac5f77ed5e0221ce6d84b5').then((content) =&gt; {
-            assert.equal(content['status'], 'NotFound');
-        });
-    });
-
-    it('should return the meta data of the file with the specified SHA256', () =&gt; {
-        let uploadedFile;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            uploadedFile = response['uploadedFile'];
-            return TestServer.remoteAPI().getJSON(`/api/uploaded-file/?sha256=${uploadedFile['sha256']}`);
-        }).then((response) =&gt; {
-            assert.deepEqual(uploadedFile, response['uploadedFile']);
-        });
-    });
-
-    it('should return &quot;NotFound&quot; when the file matching the specified SHA256 had already been deleted', () =&gt; {
-        let uploadedFile;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            uploadedFile = response['uploadedFile'];
-            const db = TestServer.database();
-            return db.connect().then(() =&gt; db.query(`UPDATE uploaded_files SET file_deleted_at = now() at time zone 'utc'`));
-        }).then(() =&gt; {
-            return TestServer.remoteAPI().getJSON(`/api/uploaded-file/?sha256=${uploadedFile['sha256']}`);
-        }).then((content) =&gt; {
-            assert.equal(content['status'], 'NotFound');
-        });
-    });
-
-
-    it('should respond with ETag, Acccept-Ranges, Content-Disposition, Content-Length, and Last-Modified headers', () =&gt; {
-        let uploadedFile;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            uploadedFile = response['uploadedFile'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${uploadedFile['id']}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            const headers = response.headers;
-
-            assert(Object.keys(headers).includes('etag'));
-            assert.equal(headers['etag'], uploadedFile['sha256']);
-
-            assert(Object.keys(headers).includes('accept-ranges'));
-            assert.equal(headers['accept-ranges'], 'bytes');
-
-            assert(Object.keys(headers).includes('content-disposition'));
-            assert.equal(headers['content-disposition'], `attachment; filename*=utf-8''some.dat`);
-
-            assert(Object.keys(headers).includes('content-length'));
-            assert.equal(headers['content-length'], uploadedFile['size']);
-
-            assert(Object.keys(headers).includes('last-modified'));
-        });
-    });
-
-    it('should respond with the same Last-Modified each time', () =&gt; {
-        let id;
-        let lastModified;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            lastModified = response.headers['last-modified'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            assert.equal(response.headers['last-modified'], lastModified);
-        });
-    });
-
-    it('should respond with Content-Range when requested after X bytes', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=5-'}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 5-11/12');
-            assert.equal(response.responseText, 'content');
-        });
-    });
-
-    it('should respond with Content-Range when requested between X-Y bytes', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=4-9'}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 4-9/12');
-            assert.equal(response.responseText, ' conte');
-        });
-    });
-
-    it('should respond with Content-Range when requested for the last X bytes', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=-4'}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 8-11/12');
-            assert.equal(response.responseText, 'tent');
-        });
-    });
-
-    it('should respond with Content-Range for the whole content when the suffix length is larger than the content', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=-100'}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 0-11/12');
-            assert.equal(response.responseText, 'some content');
-        });
-    });
-
-    it('should return 416 when the starting byte is after the file size', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=12-'}})
-                .then(() =&gt; assert(false, 'should never be reached'), (error) =&gt; assert.equal(error, 416));
-        });
-    });
-
-    it('should return 416 when the starting byte after the ending byte', () =&gt; {
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            const id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null, {headers: {'Range': 'bytes=2-1'}})
-                .then(() =&gt; assert(false, 'should never be reached'), (error) =&gt; assert.equal(error, 416));
-        });
-    });
-
-    it('should respond with Content-Range when If-Range matches the last modified date', () =&gt; {
-        let id;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            assert.equal(response.statusCode, 200);
-            assert.equal(response.responseText, 'some content');
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
-                {headers: {'Range': 'bytes = 9-10', 'If-Range': response.headers['last-modified']}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 9-10/12');
-            assert.equal(response.responseText, 'en');
-        });
-    });
-
-    it('should respond with Content-Range when If-Range matches ETag', () =&gt; {
-        let id;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            assert.equal(response.statusCode, 200);
-            assert.equal(response.responseText, 'some content');
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
-                {headers: {'Range': 'bytes = 9-10', 'If-Range': response.headers['etag']}});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], 'bytes 9-10/12');
-            assert.equal(response.responseText, 'en');
-        });
-    });
-
-    it('should return the full content when If-Range does not match the last modified date or ETag', () =&gt; {
-        let id;
-        return TemporaryFile.makeTemporaryFile('some.dat', 'some content').then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null);
-        }).then((response) =&gt; {
-            assert.equal(response.statusCode, 200);
-            assert.equal(response.responseText, 'some content');
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
-                {'Range': 'bytes = 9-10', 'If-Range': 'foo'});
-        }).then((response) =&gt; {
-            assert.equal(response.statusCode, 200);
-            assert.equal(response.responseText, 'some content');
-        });
-    });
-
-    it('should respond with Content-Range across 64KB streaming chunks', () =&gt; {
-        let id;
-        const fileSize = 256 * 1024;
-        const tokens = &quot;0123456789abcdefghijklmnopqrstuvwxyz&quot;;
-        let buffer = Buffer.allocUnsafe(fileSize);
-        for (let i = 0; i &lt; fileSize; i++)
-            buffer[i] = Math.floor(Math.random() * 256);
-        let startByte = 63 * 1024;
-        let endByte = 128 * 1024 - 1;
-
-        let responseBufferList = [];
-        const responseHandler = (response) =&gt; {
-            response.on('data', (chunk) =&gt; responseBufferList.push(chunk));
-        };
-
-        function verifyBuffer()
-        {
-            const responseBuffer = Buffer.concat(responseBufferList);
-            for (let i = 0; i &lt; endByte - startByte + 1; i++) {
-                const actual = responseBuffer[i];
-                const expected = buffer[startByte + i];
-                assert.equal(actual, expected, `The byte at index ${i} should be identical. Expected ${expected} but got ${actual}`);
-            }
-        }
-
-        return TemporaryFile.makeTemporaryFile('some.dat', buffer).then((stream) =&gt; {
-            return PrivilegedAPI.sendRequest('upload-file', {newFile: stream}, {useFormData: true});
-        }).then((response) =&gt; {
-            id = response['uploadedFile']['id'];
-            return TestServer.remoteAPI().sendHttpRequest(`/api/uploaded-file/${id}`, 'GET', null, null,
-                {headers: {'Range': `bytes = ${startByte}-${endByte}`}, responseHandler});
-        }).then((response) =&gt; {
-            const headers = response.headers;
-            assert.equal(response.statusCode, 206);
-            assert.equal(headers['content-range'], `bytes ${startByte}-${endByte}/${fileSize}`);
-            verifyBuffer();
-        });
-    });
-
-});
</del></span></pre>
</div>
</div>

</body>
</html>