<!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>[201828] 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/201828">201828</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-06-08 13:43:01 -0700 (Wed, 08 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>sync-buildbot.js should update the list of tests and platforms associated with a triggerable
https://bugs.webkit.org/show_bug.cgi?id=158406

Reviewed by Chris Dumez.

Add /api/update-triggerable and a test for it, which were supposed to be added in <a href="http://trac.webkit.org/projects/webkit/changeset/201718">r201718</a>
but for which I forgot to run svn add.

* public/api/update-triggerable.php: Added.
(main):
* server-tests/api-update-triggerable.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgpublicapiupdatetriggerablephp">trunk/Websites/perf.webkit.org/public/api/update-triggerable.php</a></li>
<li><a href="#trunkWebsitesperfwebkitorgservertestsapiupdatetriggerablejs">trunk/Websites/perf.webkit.org/server-tests/api-update-triggerable.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 (201827 => 201828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2016-06-08 20:21:40 UTC (rev 201827)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2016-06-08 20:43:01 UTC (rev 201828)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-06-08  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        sync-buildbot.js should update the list of tests and platforms associated with a triggerable
+        https://bugs.webkit.org/show_bug.cgi?id=158406
+
+        Reviewed by Chris Dumez.
+
+        Add /api/update-triggerable and a test for it, which were supposed to be added in r201718
+        but for which I forgot to run svn add.
+
+        * public/api/update-triggerable.php: Added.
+        (main):
+        * server-tests/api-update-triggerable.js: Added.
+
</ins><span class="cx"> 2016-06-07  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Build fix after r201739. attachShadow was throwing an exception on this component.
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicapiupdatetriggerablephp"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/api/update-triggerable.php (0 => 201828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/api/update-triggerable.php                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/api/update-triggerable.php        2016-06-08 20:43:01 UTC (rev 201828)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+&lt;?php
+
+require('../include/json-header.php');
+
+function main($post_data) {
+    $db = new Database;
+    if (!$db-&gt;connect())
+        exit_with_error('DatabaseConnectionFailure');
+
+    $report = json_decode($post_data, true);
+    verify_slave($db, $report);
+
+    $triggerable_name = array_get($report, 'triggerable');
+    $triggerable = $db-&gt;select_first_row('build_triggerables', 'triggerable', array('name' =&gt; $triggerable_name));
+    if (!$triggerable)
+        exit_with_error('TriggerableNotFound', array('triggerable' =&gt; $triggerable_name));
+    $triggerable_id = $triggerable['triggerable_id'];
+
+    $configurations = array_get($report, 'configurations');
+    if (!is_array($configurations))
+        exit_with_error('InvalidConfigurations', array('configurations' =&gt; $configurations));
+
+    foreach ($configurations as $entry) {
+        if (!is_array($entry) || !array_key_exists('test', $entry) || !array_key_exists('platform', $entry))
+            exit_with_error('InvalidConfigurationEntry', array('configurationEntry' =&gt; $entry));
+    }
+
+    $db-&gt;begin_transaction();
+    if ($db-&gt;query_and_get_affected_rows('DELETE FROM triggerable_configurations WHERE trigconfig_triggerable = $1', array($triggerable_id)) === false) {
+        $db-&gt;rollback_transaction();
+        exit_with_error('FailedToDeleteExistingConfigurations', array('triggerable' =&gt; $triggerable_id));
+    }
+
+    foreach ($configurations as $entry) {
+        $config_info = array('test' =&gt; $entry['test'], 'platform' =&gt; $entry['platform'], 'triggerable' =&gt; $triggerable_id);
+        if (!$db-&gt;insert_row('triggerable_configurations', 'trigconfig', $config_info, null)) {
+            $db-&gt;rollback_transaction();
+            exit_with_error('FailedToInsertConfiguration', array('entry' =&gt; $entry));
+        }
+    }
+
+    $db-&gt;commit_transaction();
+    exit_with_success();
+}
+
+main($HTTP_RAW_POST_DATA);
+
+?&gt;
</ins></span></pre></div>
<a id="trunkWebsitesperfwebkitorgservertestsapiupdatetriggerablejs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/server-tests/api-update-triggerable.js (0 => 201828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/server-tests/api-update-triggerable.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/server-tests/api-update-triggerable.js        2016-06-08 20:43:01 UTC (rev 201828)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+'use strict';
+
+const assert = require('assert');
+
+require('../tools/js/v3-models.js');
+
+const TestServer = require('./resources/test-server.js');
+const MockData = require('./resources/mock-data.js');
+const addSlaveForReport = require('./resources/common-operations.js').addSlaveForReport;
+const connectToDatabaseInEveryTest = require('./resources/common-operations.js').connectToDatabaseInEveryTest;
+
+describe('/api/update-triggerable/', function () {
+    this.timeout(1000);
+    TestServer.inject();
+    connectToDatabaseInEveryTest();
+
+    const emptyUpdate = {
+        'slaveName': 'someSlave',
+        'slavePassword': 'somePassword',
+        'triggerable': 'build-webkit',
+        'configurations': [],
+    };
+
+    const smallUpdate = {
+        'slaveName': 'someSlave',
+        'slavePassword': 'somePassword',
+        'triggerable': 'build-webkit',
+        'configurations': [
+            {test: MockData.someTestId(), platform: MockData.somePlatformId()}
+        ],
+    };
+
+    it('should reject when slave name is missing', function (done) {
+        TestServer.remoteAPI().postJSON('/api/update-triggerable/', {}).then(function (response) {
+            assert.equal(response['status'], 'MissingSlaveName');
+            done();
+        }).catch(done);
+    });
+
+    it('should reject when there are no slaves', function (done) {
+        const update = {slaveName: emptyUpdate.slaveName, slavePassword: emptyUpdate.slavePassword};
+        TestServer.remoteAPI().postJSON('/api/update-triggerable/', update).then(function (response) {
+            assert.equal(response['status'], 'SlaveNotFound');
+            done();
+        }).catch(done);
+    });
+
+    it('should reject when the slave password doesn\'t match', function (done) {
+        MockData.addMockData(TestServer.database()).then(function () {
+            return addSlaveForReport(emptyUpdate);
+        }).then(function () {
+            const report = {slaveName: emptyUpdate.slaveName, slavePassword: 'badPassword'};
+            return TestServer.remoteAPI().postJSON('/api/update-triggerable/', emptyUpdate);
+        }).then(function (response) {
+            assert.equal(response['status'], 'OK');
+            done();
+        }).catch(done);
+    });
+
+    it('should accept an empty report', function (done) {
+        MockData.addMockData(TestServer.database()).then(function () {
+            return addSlaveForReport(emptyUpdate);
+        }).then(function () {
+            return TestServer.remoteAPI().postJSON('/api/update-triggerable/', emptyUpdate);
+        }).then(function (response) {
+            assert.equal(response['status'], 'OK');
+            done();
+        }).catch(done);
+    });
+
+    it('delete existing configurations when accepting an empty report', function (done) {
+        const db = TestServer.database();
+        MockData.addMockData(db).then(function () {
+            return Promise.all([
+                addSlaveForReport(emptyUpdate),
+                db.insert('triggerable_configurations',
+                    {'triggerable': 1 /* build-webkit */, 'test': MockData.someTestId(), 'platform': MockData.somePlatformId()})
+            ]);
+        }).then(function () {
+            return TestServer.remoteAPI().postJSON('/api/update-triggerable/', emptyUpdate);
+        }).then(function (response) {
+            assert.equal(response['status'], 'OK');
+            return db.selectAll('triggerable_configurations', 'test');
+        }).then(function (rows) {
+            assert.equal(rows.length, 0);
+            done();
+        }).catch(done);
+    });
+
+    it('should add configurations in the update', function (done) {
+        const db = TestServer.database();
+        MockData.addMockData(db).then(function () {
+            return addSlaveForReport(smallUpdate);
+        }).then(function () {
+            return TestServer.remoteAPI().postJSON('/api/update-triggerable/', smallUpdate);
+        }).then(function (response) {
+            assert.equal(response['status'], 'OK');
+            return db.selectAll('triggerable_configurations', 'test');
+        }).then(function (rows) {
+            assert.equal(rows.length, 1);
+            assert.equal(rows[0]['test'], smallUpdate.configurations[0]['test']);
+            assert.equal(rows[0]['platform'], smallUpdate.configurations[0]['platform']);
+            done();
+        }).catch(done);
+    });
+
+    it('should reject when a configuration is malformed', function (done) {
+        const db = TestServer.database();
+        MockData.addMockData(db).then(function () {
+            return addSlaveForReport(smallUpdate);
+        }).then(function () {
+            const update = {
+                'slaveName': 'someSlave',
+                'slavePassword': 'somePassword',
+                'triggerable': 'build-webkit',
+                'configurations': [{}],
+            };
+            return TestServer.remoteAPI().postJSON('/api/update-triggerable/', update);
+        }).then(function (response) {
+            assert.equal(response['status'], 'InvalidConfigurationEntry');
+            done();
+        }).catch(done);
+    });
+
+});
</ins></span></pre>
</div>
</div>

</body>
</html>