Merge "Remove restriction of administrative permission for rerunning checks"
diff --git a/gr-checks/gr-checkers-list.html b/gr-checks/gr-checkers-list.html
new file mode 100644
index 0000000..36e8f85
--- /dev/null
+++ b/gr-checks/gr-checkers-list.html
@@ -0,0 +1,163 @@
+<link rel="import" href="gr-create-checkers-dialog.html">
+
+<!-- Expects core to import these functionalities
+ gr-list-view/gr-list-view.html
+ styles/gr-form-styles.html
+ /gr-icons/gr-icons.html
+ /iron-input/iron-input.html -->
+
+<dom-module id="gr-checkers-list">
+ <template>
+ <style include="shared-styles"></style>
+ <style include="gr-table-styles"></style>
+ <style>
+ iron-icon {
+ cursor: pointer;
+ }
+ #filter {
+ font-size: var(--font-size-normal);
+ max-width: 25em;
+ }
+ #filter:focus {
+ outline: none;
+ }
+ #topContainer {
+ align-items: center;
+ display: flex;
+ height: 3rem;
+ justify-content: space-between;
+ margin: 0 1em;
+ }
+ #createNewContainer:not(.show) {
+ display: none;
+ }
+ a {
+ color: var(--primary-text-color);
+ text-decoration: none;
+ }
+ nav {
+ align-items: center;
+ display: flex;
+ height: 3rem;
+ justify-content: flex-end;
+ margin-right: 20px;
+ }
+ nav,
+ iron-icon {
+ color: var(--deemphasized-text-color);
+ }
+ .nav-iron-icon {
+ height: 1.85rem;
+ margin-left: 16px;
+ width: 1.85rem;
+ }
+ .nav-buttons:hover {
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ </style>
+
+
+ <div id="topContainer">
+ <div>
+ <label>Filter:</label>
+ <iron-input
+ type="text"
+ bind-value="{{_filter}}">
+ <input
+ is="iron-input"
+ type="text"
+ id="filter"
+ bind-value="{{_filter}}">
+ </iron-input>
+ </div>
+ <div id="createNewContainer"
+ class$="[[_computeCreateClass(_createNewCapability)]]">
+ <gr-button primary link id="createNew" on-tap="_handleCreateClicked">
+ Create New
+ </gr-button>
+ </div>
+ </div>
+
+ <table id="list" class="genericList">
+ <tr class="headerRow">
+ <th class="name topHeader">Checker Name</th>
+ <th class="name topHeader">Repository</th>
+ <th class="name topHeader">Status</th>
+ <th class="name topHeader">Required</th>
+ <th class="topHeader description">Checker Description</th>
+ <th class="name topHeader"> Edit </th>
+ </tr>
+ <tbody class$="[[computeLoadingClass(_loading)]]">
+ <template is="dom-repeat" items="[[_visibleCheckers]]">
+ <tr class="table">
+ <td class="name">
+ <a>[[item.name]]</a>
+ </td>
+ <td class="name">[[item.repository]]</td>
+ <td class="name">[[item.status]]</td>
+ <td class="name">[[_computeBlocking(item)]]</td>
+ <td class="description">[[item.description]]</td>
+ <td on-tap="_handleEditIconClicked">
+ <iron-icon icon="gr-icons:edit"></iron-icon>
+ </td>
+ </tr>
+ </template>
+ </tbody>
+ </table>
+
+ <nav>
+ <template is="dom-if" if="[[_showPrevButton]]">
+ <a class="nav-buttons" id="prevArrow"
+ on-tap="_handlePrevClicked">
+ <iron-icon class="nav-iron-icon" icon="gr-icons:chevron-left"></iron-icon>
+ </a>
+ </template>
+ <template is="dom-if" if="[[_showNextButton]]">
+ <a class="nav-buttons" id="nextArrow"
+ on-tap="_handleNextClicked">
+ <iron-icon icon="gr-icons:chevron-right"></iron-icon>
+ </a>
+ </template>
+ </nav>
+
+ <gr-overlay id="createOverlay" with-backdrop>
+ <gr-dialog
+ id="createDialog"
+ confirm-label="Create"
+ on-confirm="_handleCreateConfirm"
+ on-cancel="_handleCreateCancel">
+ <div class="header" slot="header">
+ Create Checkers
+ </div>
+ <div slot="main">
+ <gr-create-checkers-dialog
+ id="createNewModal"
+ plugin-rest-api="[[pluginRestApi]]">
+ </gr-create-checkers-dialog>
+ </div>
+ </gr-dialog>
+ </gr-overlay>
+ <gr-overlay id="editOverlay" with-backdrop>
+ <gr-dialog
+ id="editDialog"
+ confirm-label="Save"
+ on-confirm="_handleEditConfirm"
+ on-cancel="_handleEditCancel">
+ <div class="header" slot="header">
+ Edit Checker
+ </div>
+ <div slot="main">
+ <gr-create-checkers-dialog
+ checker="[[checker]]"
+ plugin-rest-api="[[pluginRestApi]]"
+ on-cancel="_handleEditCancel"
+ id="editModal">
+ </gr-create-checkers-dialog>
+ </div>
+ </gr-dialog>
+ </gr-overlay>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="gr-checkers-list.js"></script>
+</dom-module>
diff --git a/gr-checks/gr-checkers-list.js b/gr-checks/gr-checkers-list.js
new file mode 100644
index 0000000..0967c03
--- /dev/null
+++ b/gr-checks/gr-checkers-list.js
@@ -0,0 +1,174 @@
+(function() {
+ 'use strict';
+ const CHECKERS_PER_PAGE = 15;
+ const GET_CHECKERS_URL = "/a/plugins/checks/checkers/";
+
+ /**
+ * Show a list of all checkers along with creating/editing them
+ */
+ Polymer({
+ is: 'gr-checkers-list',
+ properties: {
+ pluginRestApi: Object,
+ // Checker that will be passed to the editOverlay modal
+ checker: Object,
+ _checkers: Array,
+ // List of checkers that contain the filtered text
+ _filteredCheckers: Array,
+ _loading: {
+ type: Boolean,
+ value: true,
+ },
+ _filter: {
+ type: String,
+ value: '',
+ },
+ _visibleCheckers: {
+ type: Array,
+ computed: '_computeVisibleCheckers(_startingIndex, _filteredCheckers)',
+ observer: '_visibleCheckersChanged'
+ },
+ _createNewCapability: {
+ type: Boolean,
+ value: true,
+ },
+ _startingIndex: {
+ type: Number,
+ value: 0
+ },
+ _showNextButton: {
+ type: Boolean,
+ value: true,
+ computed: '_computeShowNextButton(_startingIndex, _filteredCheckers)'
+ },
+ _showPrevButton: {
+ type: Boolean,
+ value: true,
+ computed: '_computeShowPrevButton(_startingIndex, _filteredCheckers)'
+ },
+ },
+ observers: [
+ '_showCheckers(_checkers, _filter)',
+ ],
+
+ attached() {
+ this._getCheckers();
+ },
+
+ _contains(target, keyword) {
+ return target.toLowerCase().includes(keyword.toLowerCase().trim());
+ },
+
+ _visibleCheckersChanged(currentVisibleCheckers, previousVisibleCheckers) {
+ if (!currentVisibleCheckers || !previousVisibleCheckers) {
+ return;
+ }
+ if (currentVisibleCheckers.length !== previousVisibleCheckers.length) {
+ this.fire('resize', {bubbles: false});
+ }
+ },
+
+ _showCheckers(_checkers, _filter) {
+ if (!_checkers) return;
+ if (!_filter) _filter = '';
+ // TODO(dhruvsri): highlight matching part
+ this._filteredCheckers = this._checkers.filter(checker =>
+ this._contains(checker.name, this._filter) ||
+ this._contains(checker.repository, this._filter))
+ this._startingIndex = 0;
+ },
+
+ computeLoadingClass(loading) {
+ return loading ? 'loading' : '';
+ },
+
+ _computeVisibleCheckers(_startingIndex, _filteredCheckers) {
+ if (!_filteredCheckers) {
+ return [];
+ }
+ return this._filteredCheckers.slice(this._startingIndex,
+ this._startingIndex + CHECKERS_PER_PAGE);
+ },
+
+ _computeShowNextButton(_startingIndex, _filteredCheckers) {
+ if (!_filteredCheckers) {
+ return false;
+ }
+ return _startingIndex + CHECKERS_PER_PAGE < _filteredCheckers.length;
+ },
+
+ _computeShowPrevButton(_startingIndex, _filteredCheckers) {
+ if (!_filteredCheckers) {
+ return false;
+ }
+ return _startingIndex >= CHECKERS_PER_PAGE;
+ },
+
+ _handleNextClicked() {
+ if (this._startingIndex + CHECKERS_PER_PAGE <
+ this._filteredCheckers.length) {
+ this._startingIndex += CHECKERS_PER_PAGE;
+ }
+ },
+
+ _handlePrevClicked() {
+ if (this._startingIndex >= CHECKERS_PER_PAGE) {
+ this._startingIndex -= CHECKERS_PER_PAGE;
+ }
+ },
+
+ _getCheckers() {
+ this.pluginRestApi.fetchJSON({
+ method: 'GET',
+ url: GET_CHECKERS_URL,
+ }).then(checkers => {
+ if (!checkers) { return; }
+ this._checkers = checkers;
+ this._startingIndex = 0;
+ this._loading = false;
+ });
+ },
+
+ _handleEditConfirm() {
+ this.$.editModal.handleEditChecker();
+ },
+
+ _handleEditIconClicked(e) {
+ let checker = e.model.item;
+ this.checker = checker;
+ this.$.editOverlay.open();
+ },
+
+ _handleEditCancel(e) {
+ if (e.detail.reload) {
+ this._getCheckers();
+ }
+ this.$.editOverlay.close();
+ },
+
+ _computeCreateClass(createNew) {
+ return createNew ? 'show' : '';
+ },
+
+ _computeBlocking(checker) {
+ return (checker && checker.blocking && checker.blocking.length > 0)
+ ? "YES": "NO";
+ },
+
+ _handleCreateConfirm() {
+ this.$.createNewModal.handleCreateChecker();
+ },
+
+ _handleCreateClicked() {
+ this.$.createOverlay.open();
+ },
+
+ _handleCreateCancel(e) {
+ if (e.detail.reload) {
+ this._getCheckers();
+ }
+ this.$.createOverlay.close();
+ },
+
+ })
+})();
\ No newline at end of file
diff --git a/gr-checks/gr-checks-item.html b/gr-checks/gr-checks-item.html
index 602cffb..374f76b 100644
--- a/gr-checks/gr-checks-item.html
+++ b/gr-checks/gr-checks-item.html
@@ -38,20 +38,21 @@
<td>[[_startTime]]</td>
<td>[[_duration]]</td>
<td>
- <a href$="[[check.url]]" target="_blank" class="log">
- <gr-button link no-uppercase disabled="[[!check.url]]">
- View log
- </gr-button>
- </a>
-<!-- disabling re-run button until the API for rerun is ready-->
-<!-- <gr-button-->
-<!-- link-->
-<!-- no-uppercase-->
-<!-- on-tap="handleClick">-->
-<!-- Re-run-->
-<!-- </gr-button>-->
- </td>
- <td>[[check.checker_description]]</td>
+ <a href$="[[check.url]]" target="_blank" class="log">
+ <gr-button link no-uppercase disabled="[[!check.url]]">
+ View log
+ </gr-button>
+ </a>
+ </td>
+ <td>
+ <gr-button
+ link
+ no-uppercase
+ on-tap="_handleReRunClicked">
+ Re-run
+ </gr-button>
+ </td>
+ <td>[[check.checker_description]]</td>
</template>
<script src="gr-checks-item.js"></script>
</dom-module>
diff --git a/gr-checks/gr-checks-item.js b/gr-checks/gr-checks-item.js
index 2c0d98b..0f04f56 100644
--- a/gr-checks/gr-checks-item.js
+++ b/gr-checks/gr-checks-item.js
@@ -29,7 +29,6 @@
/** @type {Defs.Check} */
check: Object,
/** @type {function(string): !Promise<!Object>} */
- retryCheck: Function,
_startTime: {
type: String,
computed: '_computeStartTime(check)',
@@ -49,6 +48,13 @@
},
/**
+ * Fired when the retry check button is pressed.
+ *
+ * @event retry-check
+ */
+
+
+ /**
* @param {!Defs.Check} check
* @return {string}
*/
@@ -87,9 +93,9 @@
_computeRequiredForMerge(check) {
return (check.blocking && check.blocking.length === 0) ? "Optional" : "Required";
},
- handleClick(event) {
- event.preventDefault();
- this.retryCheck(this.check.checker_uuid);
+ _handleReRunClicked(event) {
+ this.fire('retry-check',{uuid: this.check.checker_uuid},
+ {bubbles: false});
},
});
diff --git a/gr-checks/gr-checks-view.html b/gr-checks/gr-checks-view.html
index 8a771c3..40b6390 100644
--- a/gr-checks/gr-checks-view.html
+++ b/gr-checks/gr-checks-view.html
@@ -1,4 +1,6 @@
<link rel="import" href="gr-checks-status.html">
+<link rel="import" href="gr-checkers-list.html">
+
<dom-module id="gr-checks-view">
<template>
<style>
@@ -84,8 +86,20 @@
padding-left: 1em;
}
+ .configure-button {
+ float:right;
+ margin-top: 10px;
+ }
+
+ #listOverlay {
+ width: 75%;
+ }
</style>
+ <template is="dom-if" if="[[_createCheckerCapability]]">
+ <gr-button class="configure-button" on-tap="_handleConfigureClicked"> Configure </gr-button>
+ </template>
+
<template is="dom-if" if="[[_isLoading(_status)]]">
<div class="no-content">
<p>Loading...</p>
@@ -122,26 +136,27 @@
<th class="topHeader">Started</th>
<th class="topHeader">Duration</th>
<th class="topHeader"><!-- actions --></th>
+ <th class="topHeader"><!-- re-run --></th>
<th class="topHeader">Description</th>
</tr>
</thead>
<tbody>
<template is="dom-repeat" items="[[_checks]]" as="check">
<tr>
- <gr-checks-item on-toggle-check-message="_toggleCheckMessage"
- check="[[check]]" retry-check="[[retryCheck]]">
+ <gr-checks-item on-retry-check="_handleRetryCheck" on-toggle-check-message="_toggleCheckMessage"
+ check="[[check]]">
</gr-checks-item>
</tr>
<template is="dom-if" if="[[check.showCheckMessage]]">
<tr>
- <td colspan="9" class="check-message-heading">
+ <td colspan="10" class="check-message-heading">
<span class="message-heading">
Message
</span>
</td>
</tr>
<tr>
- <td colspan="9" class="check-message">
+ <td colspan="10" class="check-message">
<span class="message"> [[check.message]] </span>
</td>
</tr>
@@ -150,7 +165,11 @@
</tbody>
</table>
</template>
- </template>
+ <gr-overlay id="listOverlay" with-backdrop>
+ <gr-checkers-list on-resize="_handleCheckersListResize" plugin-rest-api="[[pluginRestApi]]"></gr-checkers-list>
+ </gr-overlay>
+
+ </template>
<script src="gr-checks-view.js"></script>
</dom-module>
diff --git a/gr-checks/gr-checks-view.js b/gr-checks/gr-checks-view.js
index bf28841..3aa88b8 100644
--- a/gr-checks/gr-checks-view.js
+++ b/gr-checks/gr-checks-view.js
@@ -47,28 +47,60 @@
/** @type {function(string): !Promise<Boolean>} */
isConfigured: Function,
/** @type {function(string, string): !Promise<!Object>} */
- retryCheck: Function,
+ pluginRestApi: Object,
_checks: Object,
_status: {
type: Object,
value: LoadingStatus.LOADING,
},
- pollChecksInterval: Object,
+ pollChecksInterval: Number,
visibilityChangeListenerAdded: {
type: Boolean,
value: false
- }
+ },
+ _createCheckerCapability: {
+ type: Boolean,
+ value: false
+ },
},
observers: [
'_pollChecksRegularly(change, revision, getChecks)',
],
+ attached() {
+ this.pluginRestApi = this.plugin.restApi();
+ this._initCreateCheckerCapability();
+ },
+
detached() {
clearInterval(this.pollChecksInterval);
this.unlisten(document, 'visibilitychange', '_onVisibililityChange');
},
+ _handleCheckersListResize() {
+ // Force polymer to recalculate position of overlay when length of
+ // checkers changes
+ this.$.listOverlay.refit();
+ },
+
+ _initCreateCheckerCapability() {
+ return this.pluginRestApi.getAccount().then(account => {
+ if (!account) { return; }
+ return this.pluginRestApi
+ .getAccountCapabilities(['checks-administrateCheckers'])
+ .then(capabilities => {
+ if (capabilities['checks-administrateCheckers']) {
+ this._createCheckerCapability = true;
+ }
+ });
+ });
+ },
+
+ _handleConfigureClicked() {
+ this.$.listOverlay.open();
+ },
+
_orderChecks(a, b) {
if (a.state != b.state) {
let indexA = StatusPriorityOrder.indexOf(a.state);
@@ -86,6 +118,22 @@
return a.checker_name.localeCompare(b.checker_name);
},
+ _handleRetryCheck(e) {
+ const uuid = e.detail.uuid;
+ const retryCheck = (change, revision, uuid) => {
+ return this.pluginRestApi.post(
+ '/changes/' + change + '/revisions/' + revision + '/checks/' + uuid + '/rerun'
+ )
+ }
+ retryCheck(this.change._number, this.revision._number, uuid).then(
+ res => {
+ this._fetchChecks(this.change, this.revision, this.getChecks);
+ }, e => {
+ console.error(e);
+ }
+ )
+ },
+
/**
* @param {!Defs.Change} change
* @param {!Defs.Revision} revision
diff --git a/gr-checks/gr-checks.html b/gr-checks/gr-checks.html
index cc4f6ca..ceed087 100644
--- a/gr-checks/gr-checks.html
+++ b/gr-checks/gr-checks.html
@@ -12,7 +12,7 @@
const getChecks = (change, revision) => {
return plugin.restApi().get(
- '/changes/' + change + '/revisions/' + revision + '/checks?o=CHECKER');
+ '/changes/' + change + '/revisions/' + revision + '/checks?o=CHECKER');
};
// TODO(brohlfs): Enable this dashboard column when search queries start
@@ -24,23 +24,23 @@
// 'change-list-item-cell',
// 'gr-checks-change-list-item-cell-view');
plugin.registerCustomComponent(
- 'commit-container',
- 'gr-checks-chip-view').onAttached(
- view => {
- view['getChecks'] = getChecks;
- });
+ 'commit-container',
+ 'gr-checks-chip-view').onAttached(
+ view => {
+ view['getChecks'] = getChecks;
+ }
+ );
plugin.registerDynamicCustomComponent(
- 'change-view-tab-header',
- 'gr-checks-change-view-tab-header-view');
+ 'change-view-tab-header',
+ 'gr-checks-change-view-tab-header-view'
+ );
plugin.registerDynamicCustomComponent(
- 'change-view-tab-content',
- 'gr-checks-view').onAttached(
- view => {
- view['isConfigured'] = (repository) => Promise.resolve(true);
- // TODO(brohlfs): Implement retry.
- view['retryCheck'] = (buildId) => undefined;
- view['getChecks'] = getChecks;
- });
- });
+ 'change-view-tab-content',
+ 'gr-checks-view').onAttached(
+ view => {
+ view['isConfigured'] = (repository) => Promise.resolve(true);
+ view['getChecks'] = getChecks;
+ });
+ });
</script>
</dom-module>
diff --git a/gr-checks/gr-create-checkers-dialog.html b/gr-checks/gr-create-checkers-dialog.html
new file mode 100644
index 0000000..e9aad47
--- /dev/null
+++ b/gr-checks/gr-create-checkers-dialog.html
@@ -0,0 +1,157 @@
+<link rel="import" href="gr-repo-chip.html">
+<dom-module id="gr-create-checkers-dialog">
+ <template>
+ <style include="gr-form-styles">
+ :host {
+ display: inline-block;
+ }
+ input {
+ width: 20em;
+ }
+ gr-autocomplete {
+ border: none;
+ --gr-autocomplete: {
+ border: 1px solid var(--border-color);
+ border-radius: 2px;
+ font-size: var(--font-size-normal);
+ height: 2em;
+ padding: 0 .15em;
+ width: 20em;
+ }
+ }
+ .error {
+ color: red;
+ }
+ #checkerSchemaInput[disabled] {
+ background-color: var(--table-subheader-background-color);
+ }
+ #checkerIdInput[disabled] {
+ background-color: var(--table-subheader-background-color);
+ }
+ </style>
+
+ <div class="gr-form-styles">
+ <div id="form">
+ <section hidden$="[[_errorMsg.length > 0]]">
+ <span class="error"> {{_errorMsg}} </span>
+ </section>
+ <section>
+ <span class="title">Name*</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_name}}">
+ <input is="iron-input"
+ id="checkerNameInput"
+ autocomplete="on"
+ bind-value="{{_name}}">
+ </iron-input>
+ </section>
+ <section>
+ <span class="title">Description</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_description}}">
+ <input is="iron-input"
+ id="checkerDescriptionInput"
+ autocomplete="on"
+ bind-value="{{_description}}">
+ </iron-input>
+ </section>
+ <section>
+ <span class="title">Repository*</span>
+ <div class="list">
+ <template id="chips" is="dom-repeat" items="[[_repos]]" as="repo">
+ <gr-repo-chip
+ repo="[[repo]]"
+ on-keydown="_handleChipKeydown"
+ on-remove="_handleOnRemove"
+ tabindex="-1">
+ </gr-repo-chip>
+ </template>
+ </div>
+ <div hidden$="[[_repositorySelected]]">
+ <gr-autocomplete
+ id="input"
+ threshold="[[suggestFrom]]"
+ query="[[_getRepoSuggestions]]"
+ on-commit="_handleRepositorySelected"
+ clear-on-commit
+ warn-uncommitted
+ text="{{_inputText}}">
+ </gr-autocomplete>
+ </div>
+ </section>
+
+ <section>
+ <span class="title">Scheme*</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_scheme}}">
+ <input is="iron-input"
+ id="checkerSchemaInput"
+ disabled$="[[_edit]]"
+ autocomplete="on"
+ bind-value="{{_scheme}}">
+ </iron-input>
+ </section>
+
+ <section>
+ <span class="title">ID*</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_id}}">
+ <input is="iron-input"
+ id="checkerIdInput"
+ disabled$="[[_edit]]"
+ autocomplete="on"
+ bind-value="{{_id}}">
+ </iron-input>
+ </section>
+
+ <section>
+ <span class="title">Url</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_url}}">
+ <input is="iron-input"
+ id="checkerUrlInput"
+ autocomplete="on"
+ bind-value="{{_url}}">
+ </iron-input>
+ </section>
+
+ <section>
+ <span class="title"> UUID {{_uuid}}</span>
+ </section>
+
+ <section>
+ <span class="title">Status</span>
+ <gr-dropdown-list
+ items="[[_statuses]]"
+ on-value-change="_handleStatusChange"
+ text="Status"
+ value="[[_status]]">
+ </gr-dropdown-list>
+ </section>
+
+ <section>
+ <span class="title">Required</span>
+ <input
+ on-click = "_handleRequiredCheckBoxClicked"
+ type="checkbox"
+ id="privateChangeCheckBox"
+ checked$="[[_required]]">
+ </section>
+
+ <section>
+ <span class="title">Query</span>
+ <iron-input autocomplete="on"
+ bind-value="{{_query}}">
+ <input is="iron-input"
+ id="checkerQueryInput"
+ autocomplete="on"
+ bind-value="{{_query}}">
+ </iron-input>
+ </section>
+
+ </div>
+ </div>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="gr-create-checkers-dialog.js"></script>
+</dom-module>
diff --git a/gr-checks/gr-create-checkers-dialog.js b/gr-checks/gr-create-checkers-dialog.js
new file mode 100644
index 0000000..cdb4127
--- /dev/null
+++ b/gr-checks/gr-create-checkers-dialog.js
@@ -0,0 +1,258 @@
+(function() {
+ 'use strict';
+
+ const REPOS_PER_PAGE = 6;
+ const CREATE_CHECKER_URL = '/plugins/checks/checkers/';
+ const SCHEME_PATTERN = /^[\w-_.]*$/;
+
+ Polymer({
+ is: 'gr-create-checkers-dialog',
+ _legacyUndefinedCheck: true,
+
+ properties: {
+ checker: {
+ type: Object,
+ observer: '_checkerChanged'
+ },
+ _name: String,
+ _scheme: String,
+ _id: String,
+ _uuid: {
+ type: String,
+ value: ""
+ },
+ pluginRestApi: Object,
+ _url: String,
+ _description: String,
+ _getRepoSuggestions: {
+ type: Function,
+ value() {
+ return this._repoSuggestions.bind(this)
+ }
+ },
+ // The backend might support multiple repos in the future
+ // which is why I decided to keep it as an array.
+ _repos: {
+ type: Array,
+ value: [],
+ notify: true,
+ },
+ _repositorySelected: {
+ type: Boolean,
+ value: false
+ },
+ _handleOnRemove: Function,
+ _errorMsg: {
+ type: String,
+ value: ''
+ },
+ _statuses: {
+ type: Array,
+ value: [
+ {
+ "text": "ENABLED",
+ "value": "ENABLED"
+ },
+ {
+ "text": "DISABLED",
+ "value": "DISABLED"
+ }
+ ],
+ readOnly: true
+ },
+ _required: {
+ type: Boolean,
+ value: false
+ },
+ _status: String,
+ _edit: {
+ type: Boolean,
+ value: false
+ },
+ _query: String
+ },
+
+ behaviours: [
+ Gerrit.FireBehavior,
+ ],
+ /**
+ * Fired when the cancel button is pressed.
+ *
+ * @event cancel
+ */
+
+
+ observers: [
+ '_updateUUID(_scheme, _id)',
+ ],
+
+ _checkerChanged() {
+ if (!this.checker) {
+ console.warn("checker not set");
+ return;
+ }
+ this._edit = true;
+ this._scheme = this.checker.uuid.split(':')[0];
+ this._id = this.checker.uuid.split(':')[1];
+ this._name = this.checker.name;
+ this._description = this.checker.description || '';
+ this._url = this.checker.url || '';
+ this._query = this.checker.query || '';
+ this._required = this.checker.blocking &&
+ this.checker.blocking.length > 0;
+ if (this.checker.repository) {
+ this._repositorySelected = true;
+ this.set('_repos', [{name: this.checker.repository}]);
+ }
+ this._status = this.checker.status;
+ },
+
+ _updateUUID(_scheme, _id) {
+ this._uuid = _scheme + ":" + _id;
+ },
+
+ _handleStatusChange(e) {
+ this._status = e.detail.value;
+ },
+
+ _validateRequest() {
+ if (!this._name) {
+ this._errorMsg = 'Name cannot be empty';
+ return false;
+ }
+ if (this._description && this._description.length > 1000) {
+ this._errorMsg = 'Description should be less than 1000 characters';
+ return false;
+ }
+ if (!this._repositorySelected) {
+ this._errorMsg = 'Select a repository';
+ return false;
+ }
+ if (!this._scheme) {
+ this._errorMsg = 'Scheme cannot be empty.';
+ return false;
+ }
+ if (this._scheme.match(SCHEME_PATTERN) == null) {
+ this._errorMsg =
+ 'Scheme must contain [A-Z], [a-z], [0-9] or {"-" , "_" , "."}';
+ return false;
+ }
+ if (this._scheme.length > 100) {
+ this._errorMsg = 'Scheme must be shorter than 100 characters';
+ return false;
+ }
+ if (!this._id) {
+ this._errorMsg = 'ID cannot be empty.';
+ return false;
+ }
+ if (this._id.match(SCHEME_PATTERN) == null) {
+ this._errorMsg =
+ 'ID must contain [A-Z], [a-z], [0-9] or {"-" , "_" , "."}';
+ return false;
+ }
+ return true;
+ },
+
+ // TODO(dhruvsri): make sure dialog is scrollable.
+
+ _createChecker(checker) {
+ return this.pluginRestApi.send(
+ 'POST',
+ CREATE_CHECKER_URL,
+ checker,
+ )
+ },
+
+ _editChecker(checker) {
+ const url = CREATE_CHECKER_URL + checker.uuid;
+ return this.pluginRestApi.send(
+ 'POST',
+ url,
+ checker
+ )
+ },
+
+ handleEditChecker() {
+ if (!this._validateRequest()) return;
+ this._editChecker(this._getCheckerRequestObject()).then(
+ res => {
+ if (res) {
+ this._errorMsg = '';
+ this.fire('cancel', {reload: true}, {bubbles: true});
+ }
+ },
+ error => {
+ this._errorMsg = error;
+ }
+ )
+ },
+
+ _getCheckerRequestObject() {
+ return {
+ "name" : this._name,
+ "description" : this._description || '',
+ "uuid" : this._uuid,
+ "repository": this._repos[0].name,
+ "url" : this._url,
+ "status": this._status,
+ "blocking": this._required ? ["STATE_NOT_PASSING"] : [],
+ "query": this._query
+ }
+ },
+
+ handleCreateChecker() {
+ if (!this._validateRequest()) return;
+ // Currently after creating checker there is no reload happening (as
+ // this would result in the user exiting the screen).
+ this._createChecker(this._getCheckerRequestObject()).then(
+ res => {
+ if (res) this._cleanUp();
+ },
+ error => {
+ this._errorMsg = error;
+ }
+ )
+ },
+
+ _cleanUp() {
+ this._name = '';
+ this._scheme = '';
+ this._id = '';
+ this._uuid = '';
+ this._description = '';
+ this._repos = [];
+ this._repositorySelected = false;
+ this._errorMsg = '';
+ this._required = false;
+ this._query = '';
+ this._status = '';
+ this.fire('cancel', {reload: true}, {bubbles: true});
+ },
+
+ _repoSuggestions(filter) {
+ const _makeSuggestion = repo => {return {name: repo.name, value: repo}};
+ return this.pluginRestApi.getRepos(filter, REPOS_PER_PAGE).then(
+ repos => repos.map(repo => _makeSuggestion(repo))
+ )
+ },
+
+ _handleRepositorySelected(e) {
+ this.push('_repos', e.detail.value);
+ this._repositorySelected = true;
+ },
+
+ _handleRequiredCheckBoxClicked() {
+ this._required = !this._required;
+ },
+
+ _handleOnRemove(e) {
+ let idx = this._repos.indexOf(e.detail.repo);
+ if (idx == -1) return;
+ this.splice('_repos', idx, 1);
+ if (this._repos.length == 0) {
+ this._repositorySelected = false;
+ }
+ },
+
+ });
+})();
diff --git a/gr-checks/gr-repo-chip.html b/gr-checks/gr-repo-chip.html
new file mode 100644
index 0000000..b695fa9
--- /dev/null
+++ b/gr-checks/gr-repo-chip.html
@@ -0,0 +1,25 @@
+<dom-module id="gr-repo-chip">
+ <template>
+ <style>
+ iron-icon {
+ height: 1.2rem;
+ width: 1.2rem;
+ }
+ :host {
+ display: inline-block;
+ }
+ </style>
+ <span> {{repo.name}} </span>
+ <gr-button
+ id="remove"
+ link
+ hidden$="[[!removable]]"
+ tabindex="-1"
+ aria-label="Remove"
+ class="remove"
+ on-tap="_handleRemoveTap">
+ <iron-icon icon="gr-icons:close"></iron-icon>
+ </gr-button>
+ </template>
+ <script src="gr-repo-chip.js"></script>
+</dom-module>
\ No newline at end of file
diff --git a/gr-checks/gr-repo-chip.js b/gr-checks/gr-repo-chip.js
new file mode 100644
index 0000000..d63a476
--- /dev/null
+++ b/gr-checks/gr-repo-chip.js
@@ -0,0 +1,24 @@
+(function() {
+ 'use strict';
+
+ /**
+ * autocomplete chip for getting repository suggestions
+ */
+ Polymer({
+ is: 'gr-repo-chip',
+ _legacyUndefinedCheck: true,
+ properties: {
+ // repo type is ProjectInfo
+ repo: Object,
+ removable: {
+ type: Boolean,
+ value: true,
+ },
+ },
+ _handleRemoveTap(e) {
+ e.preventDefault();
+ this.fire('remove', {repo: this.repo});
+ },
+ })
+
+})();
\ No newline at end of file
diff --git a/java/com/google/gerrit/plugins/checks/CheckJson.java b/java/com/google/gerrit/plugins/checks/CheckJson.java
index 074d4cc..535fbc4 100644
--- a/java/com/google/gerrit/plugins/checks/CheckJson.java
+++ b/java/com/google/gerrit/plugins/checks/CheckJson.java
@@ -86,7 +86,7 @@
.getChecker(checkerUuid)
.ifPresent(
checker -> {
- info.checkerName = checker.getName().orElse(null);
+ info.checkerName = checker.getName();
info.checkerStatus = checker.getStatus();
info.blocking = checker.getBlockingConditions();
info.checkerDescription = checker.getDescription().orElse(null);
diff --git a/java/com/google/gerrit/plugins/checks/Checker.java b/java/com/google/gerrit/plugins/checks/Checker.java
index 075e2c9..348bd5e 100644
--- a/java/com/google/gerrit/plugins/checks/Checker.java
+++ b/java/com/google/gerrit/plugins/checks/Checker.java
@@ -39,11 +39,11 @@
/**
* Returns the display name of the checker.
*
- * <p>Checkers may not have a name, in this case {@link Optional#empty()} is returned.
+ * <p>The same name may be used by multiple checkers.
*
* @return display name of the checker
*/
- public abstract Optional<String> getName();
+ public abstract String getName();
/**
* Returns the description of the checker.
diff --git a/java/com/google/gerrit/plugins/checks/CheckerCreation.java b/java/com/google/gerrit/plugins/checks/CheckerCreation.java
index f814ce4..294f354 100644
--- a/java/com/google/gerrit/plugins/checks/CheckerCreation.java
+++ b/java/com/google/gerrit/plugins/checks/CheckerCreation.java
@@ -14,7 +14,10 @@
package com.google.gerrit.plugins.checks;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.auto.value.AutoValue;
+import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.reviewdb.client.Project;
@AutoValue
@@ -26,6 +29,13 @@
*/
public abstract CheckerUuid getCheckerUuid();
+ /**
+ * Defines the name the checker should have.
+ *
+ * <p>The same name may be used by multiple checkers.
+ */
+ public abstract String getName();
+
/** Defines the repository for which the checker applies. */
public abstract Project.NameKey getRepository();
@@ -37,8 +47,24 @@
public abstract static class Builder {
public abstract Builder setCheckerUuid(CheckerUuid checkerUuid);
+ public abstract Builder setName(String name);
+
public abstract Builder setRepository(Project.NameKey repository);
- public abstract CheckerCreation build();
+ abstract CheckerCreation autoBuild();
+
+ public CheckerCreation build() {
+ CheckerCreation checkerCreation = autoBuild();
+ checkState(!checkerCreation.getName().trim().isEmpty(), "checker name cannot be empty");
+ checkState(
+ !checkerCreation.getRepository().get().trim().isEmpty(),
+ "repository name cannot be empty");
+ return checkerCreation;
+ }
+
+ @VisibleForTesting
+ public CheckerCreation buildWithoutValidationForTesting() {
+ return autoBuild();
+ }
}
}
diff --git a/java/com/google/gerrit/plugins/checks/CheckerJson.java b/java/com/google/gerrit/plugins/checks/CheckerJson.java
index 701a169..55fdf91 100644
--- a/java/com/google/gerrit/plugins/checks/CheckerJson.java
+++ b/java/com/google/gerrit/plugins/checks/CheckerJson.java
@@ -23,7 +23,7 @@
public CheckerInfo format(Checker checker) {
CheckerInfo info = new CheckerInfo();
info.uuid = checker.getUuid().get();
- info.name = checker.getName().orElse(null);
+ info.name = checker.getName();
info.description = checker.getDescription().orElse(null);
info.url = checker.getUrl().orElse(null);
info.repository = checker.getRepository().get();
diff --git a/java/com/google/gerrit/plugins/checks/CheckerUpdate.java b/java/com/google/gerrit/plugins/checks/CheckerUpdate.java
index 97165f6..463cb1d 100644
--- a/java/com/google/gerrit/plugins/checks/CheckerUpdate.java
+++ b/java/com/google/gerrit/plugins/checks/CheckerUpdate.java
@@ -14,7 +14,10 @@
package com.google.gerrit.plugins.checks;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.auto.value.AutoValue;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
@@ -82,6 +85,27 @@
public abstract Builder setQuery(String query);
- public abstract CheckerUpdate build();
+ abstract CheckerUpdate autoBuild();
+
+ public CheckerUpdate build() {
+ CheckerUpdate checkerUpdate = autoBuild();
+
+ if (checkerUpdate.getName().isPresent()) {
+ checkState(!checkerUpdate.getName().get().trim().isEmpty(), "checker name cannot be empty");
+ }
+
+ if (checkerUpdate.getRepository().isPresent()) {
+ checkState(
+ !checkerUpdate.getRepository().get().get().trim().isEmpty(),
+ "repository name cannot be empty");
+ }
+
+ return checkerUpdate;
+ }
+
+ @VisibleForTesting
+ public CheckerUpdate buildWithoutValidationForTesting() {
+ return autoBuild();
+ }
}
}
diff --git a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
index 984cd31..e96f0c2 100644
--- a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
+++ b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
@@ -115,8 +115,13 @@
checkerCreation
.uuid()
.orElseGet(() -> CheckerUuid.parse("test:checker-" + checkerCounter.incrementAndGet()));
+ String checkerName = checkerCreation.name().orElse("Test Checker");
Project.NameKey repository = checkerCreation.repository().orElse(allProjectsName);
- return CheckerCreation.builder().setCheckerUuid(checkerUuid).setRepository(repository).build();
+ return CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(checkerName)
+ .setRepository(repository)
+ .build();
}
private static CheckerUpdate toCheckerUpdate(TestCheckerCreation checkerCreation) {
@@ -268,6 +273,10 @@
unsetValueInCheckerConfig("uuid");
}
+ if (testCheckerInvalidation.unsetName()) {
+ unsetValueInCheckerConfig("name");
+ }
+
if (testCheckerInvalidation.unsetRepository()) {
unsetValueInCheckerConfig("repository");
}
diff --git a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerInvalidation.java b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerInvalidation.java
index f845ddd..850d7c8 100644
--- a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerInvalidation.java
+++ b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerInvalidation.java
@@ -29,6 +29,8 @@
public abstract boolean unsetUuid();
+ public abstract boolean unsetName();
+
public abstract boolean unsetRepository();
public abstract boolean unsetStatus();
@@ -45,6 +47,7 @@
.invalidBlockingCondition(false)
.invalidStatus(false)
.unsetUuid(false)
+ .unsetName(false)
.unsetRepository(false)
.unsetStatus(false)
.deleteRef(false);
@@ -80,7 +83,13 @@
return unsetUuid(true);
}
- abstract Builder unsetUuid(boolean unsetUuid);
+ abstract Builder unsetUuid(boolean unsetName);
+
+ public Builder unsetName() {
+ return unsetName(true);
+ }
+
+ abstract Builder unsetName(boolean unsetName);
public Builder unsetRepository() {
return unsetRepository(true);
diff --git a/java/com/google/gerrit/plugins/checks/api/CreateChecker.java b/java/com/google/gerrit/plugins/checks/api/CreateChecker.java
index ff533a7..8ae0513 100644
--- a/java/com/google/gerrit/plugins/checks/api/CreateChecker.java
+++ b/java/com/google/gerrit/plugins/checks/api/CreateChecker.java
@@ -99,15 +99,20 @@
CheckerUuid.tryParse(input.uuid)
.orElseThrow(() -> new BadRequestException("invalid uuid: " + uuidStr));
+ String name = CheckerName.clean(input.name);
+ if (name.isEmpty()) {
+ throw new BadRequestException("name is required");
+ }
+
Project.NameKey repository = resolveRepository(input.repository);
CheckerCreation.Builder checkerCreationBuilder =
- CheckerCreation.builder().setCheckerUuid(checkerUuid).setRepository(repository);
+ CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(name)
+ .setRepository(repository);
CheckerUpdate.Builder checkerUpdateBuilder = CheckerUpdate.builder();
- String name = CheckerName.clean(input.name);
- if (!name.isEmpty()) {
- checkerUpdateBuilder.setName(name);
- }
+
if (input.description != null && !input.description.trim().isEmpty()) {
checkerUpdateBuilder.setDescription(input.description.trim());
}
diff --git a/java/com/google/gerrit/plugins/checks/db/CheckerConfig.java b/java/com/google/gerrit/plugins/checks/db/CheckerConfig.java
index 3adb2dd..2594a96 100644
--- a/java/com/google/gerrit/plugins/checks/db/CheckerConfig.java
+++ b/java/com/google/gerrit/plugins/checks/db/CheckerConfig.java
@@ -311,6 +311,11 @@
}
private void ensureThatMandatoryPropertiesAreSet() throws ConfigInvalidException {
+ if (getNewName().equals(Optional.of(""))) {
+ throw new ConfigInvalidException(
+ String.format("Name of the checker %s must be defined", describeForError()));
+ }
+
if (getNewRepository().equals(Optional.of(""))) {
throw new ConfigInvalidException(
String.format("Repository of the checker %s must be defined", describeForError()));
@@ -321,6 +326,16 @@
checkState(isLoaded, "Checker %s not loaded yet", describeForError());
}
+ private Optional<String> getNewName() {
+ if (checkerUpdate.isPresent()) {
+ return checkerUpdate.get().getName().map(Strings::nullToEmpty).map(String::trim);
+ }
+ if (checkerCreation.isPresent()) {
+ return Optional.of(Strings.nullToEmpty(checkerCreation.get().getName()).trim());
+ }
+ return Optional.empty();
+ }
+
private Optional<String> getNewRepository() {
if (checkerUpdate.isPresent()) {
return checkerUpdate
diff --git a/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java b/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
index 0b2c5ab..eabcfb2 100644
--- a/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
+++ b/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
@@ -91,16 +91,22 @@
*/
NAME("name") {
@Override
- void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
+ void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
+ throws ConfigInvalidException {
String name = config.getString(SECTION_NAME, null, super.keyName);
- if (name != null) {
- checker.setName(name);
+ if (name == null) {
+ throw new ConfigInvalidException(
+ String.format(
+ "%s.%s is not set in config file for checker %s",
+ SECTION_NAME, super.keyName, checkerUuid));
}
+ checker.setName(name);
}
@Override
void initNewConfig(Config config, CheckerCreation checkerCreation) {
- // Do nothing. Name key will be set by updateConfigValue.
+ String checkerName = checkerCreation.getName();
+ config.setString(SECTION_NAME, null, super.keyName, checkerName);
}
@Override
diff --git a/java/com/google/gerrit/plugins/checks/testing/CheckerConfigSubject.java b/java/com/google/gerrit/plugins/checks/testing/CheckerConfigSubject.java
index 8e5bb2c..2b4e356 100644
--- a/java/com/google/gerrit/plugins/checks/testing/CheckerConfigSubject.java
+++ b/java/com/google/gerrit/plugins/checks/testing/CheckerConfigSubject.java
@@ -52,10 +52,8 @@
check("uuid()").that(checker().getUuid()).isEqualTo(expectedUuid);
}
- public OptionalSubject<StringSubject, String> hasNameThat() {
- return check("name()")
- .about(optionals())
- .that(checker().getName(), StandardSubjectBuilder::that);
+ public void hasName(String expectedName) {
+ check("name()").that(checker().getName()).isEqualTo(expectedName);
}
public OptionalSubject<StringSubject, String> hasDescriptionThat() {
diff --git a/javatests/com/google/gerrit/plugins/checks/CheckerCreationTest.java b/javatests/com/google/gerrit/plugins/checks/CheckerCreationTest.java
new file mode 100644
index 0000000..36968d3
--- /dev/null
+++ b/javatests/com/google/gerrit/plugins/checks/CheckerCreationTest.java
@@ -0,0 +1,83 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.plugins.checks;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+
+import com.google.gerrit.reviewdb.client.Project;
+import org.junit.Test;
+
+public class CheckerCreationTest {
+ private final CheckerUuid checkerUuid = CheckerUuid.parse("test:my-checker");
+ private final String checkerName = "My Checker";
+ private final Project.NameKey checkerRepository = Project.nameKey("my-repo");
+
+ @Test
+ public void nameCannotBeEmpty() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName("")
+ .setRepository(checkerRepository)
+ .build());
+ assertThat(thrown).hasMessageThat().contains(String.format("checker name cannot be empty"));
+ }
+
+ @Test
+ public void nameCannotBeEmptyAfterTrim() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(" ")
+ .setRepository(checkerRepository)
+ .build());
+ assertThat(thrown).hasMessageThat().contains(String.format("checker name cannot be empty"));
+ }
+
+ @Test
+ public void repositoryCannotBeEmpty() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(checkerName)
+ .setRepository(Project.nameKey(""))
+ .build());
+ assertThat(thrown).hasMessageThat().contains(String.format("repository name cannot be empty"));
+ }
+
+ @Test
+ public void repositoryCannotBeEmptyAfterTrim() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(checkerName)
+ .setRepository(Project.nameKey(" "))
+ .build());
+ assertThat(thrown).hasMessageThat().contains(String.format("repository name cannot be empty"));
+ }
+}
diff --git a/javatests/com/google/gerrit/plugins/checks/CheckerDefinitionTest.java b/javatests/com/google/gerrit/plugins/checks/CheckerDefinitionTest.java
index 9d090ce..f0e967a 100644
--- a/javatests/com/google/gerrit/plugins/checks/CheckerDefinitionTest.java
+++ b/javatests/com/google/gerrit/plugins/checks/CheckerDefinitionTest.java
@@ -50,6 +50,7 @@
private Checker.Builder newChecker() {
return Checker.builder()
+ .setName("My Checker")
.setRepository(Project.nameKey("test-repo"))
.setStatus(CheckerStatus.ENABLED)
.setUuid(CheckerUuid.parse("schema:any-id"))
diff --git a/javatests/com/google/gerrit/plugins/checks/CheckerUpdateTest.java b/javatests/com/google/gerrit/plugins/checks/CheckerUpdateTest.java
new file mode 100644
index 0000000..ae2ed4d
--- /dev/null
+++ b/javatests/com/google/gerrit/plugins/checks/CheckerUpdateTest.java
@@ -0,0 +1,57 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.plugins.checks;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+
+import com.google.gerrit.reviewdb.client.Project;
+import org.junit.Test;
+
+public class CheckerUpdateTest {
+ @Test
+ public void nameCannotBeEmpty() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class, () -> CheckerUpdate.builder().setName("").build());
+ assertThat(thrown).hasMessageThat().contains(String.format("checker name cannot be empty"));
+ }
+
+ @Test
+ public void nameCannotBeEmptyAfterTrim() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class, () -> CheckerUpdate.builder().setName(" ").build());
+ assertThat(thrown).hasMessageThat().contains(String.format("checker name cannot be empty"));
+ }
+
+ @Test
+ public void repositoryCannotBeEmpty() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () -> CheckerUpdate.builder().setRepository(Project.nameKey("")).build());
+ assertThat(thrown).hasMessageThat().contains(String.format("repository name cannot be empty"));
+ }
+
+ @Test
+ public void repositoryCannotBeEmptyAfterTrim() {
+ IllegalStateException thrown =
+ assertThrows(
+ IllegalStateException.class,
+ () -> CheckerUpdate.builder().setRepository(Project.nameKey(" ")).build());
+ assertThat(thrown).hasMessageThat().contains(String.format("repository name cannot be empty"));
+ }
+}
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/CreateCheckerIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/CreateCheckerIT.java
index 7514878..fa36005 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/CreateCheckerIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/CreateCheckerIT.java
@@ -78,10 +78,11 @@
Timestamp expectedCreationTimestamp = TestTimeUtil.getCurrentTimestamp();
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = repositoryName.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.uuid).isEqualTo("test:my-checker");
- assertThat(info.name).isNull();
+ assertThat(info.name).isEqualTo("My Checker");
assertThat(info.description).isNull();
assertThat(info.url).isNull();
assertThat(info.repository).isEqualTo(input.repository);
@@ -104,6 +105,7 @@
public void createCheckerWithDescription() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.description = "some description";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
@@ -118,6 +120,7 @@
public void createCheckerWithUrl() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.url = "http://example.com/my-checker";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
@@ -129,27 +132,24 @@
}
@Test
- public void createCheckerWithName() throws Exception {
+ public void createCheckerWithoutNameFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
- input.name = "my-checker";
input.repository = allProjects.get();
- CheckerInfo info = checkersApi.create(input).get();
- assertThat(info.name).isEqualTo("my-checker");
- PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
- assertCommit(
- perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
+ BadRequestException thrown =
+ assertThrows(BadRequestException.class, () -> checkersApi.create(input));
+ assertThat(thrown).hasMessageThat().contains("name is required");
}
@Test
public void createCheckerNameIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
- input.name = " my-checker ";
+ input.name = " My Checker ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
- assertThat(info.name).isEqualTo("my-checker");
+ assertThat(info.name).isEqualTo("My Checker");
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
@@ -160,6 +160,7 @@
public void createCheckerDescriptionIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.description = " some description ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
@@ -174,6 +175,7 @@
public void createCheckerUrlIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.url = " http://example.com/my-checker ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
@@ -188,6 +190,7 @@
public void createCheckerRepositoryIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = " " + allProjects.get() + " ";
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.repository).isEqualTo(allProjects.get());
@@ -212,7 +215,7 @@
public void createCheckersWithSameName() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
- input.name = "my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
CheckerInfo info1 = checkersApi.create(input).get();
assertThat(info1.name).isEqualTo(input.name);
@@ -228,6 +231,7 @@
public void createCheckerWithExistingUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
checkersApi.create(input).get();
@@ -239,6 +243,7 @@
@Test
public void createCheckerWithoutUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
+ input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
@@ -250,6 +255,7 @@
public void createCheckerWithEmptyUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "";
+ input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
@@ -261,6 +267,7 @@
public void createCheckerWithEmptyUuidAfterTrimFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = " ";
+ input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
@@ -272,6 +279,7 @@
public void createCheckerWithInvalidUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = CheckerTestData.INVALID_UUID;
+ input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
@@ -283,6 +291,7 @@
public void createCheckerWithoutRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
@@ -293,6 +302,7 @@
public void createCheckerWithEmptyRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = "";
BadRequestException thrown =
@@ -304,6 +314,7 @@
public void createCheckerWithEmptyRepositoryAfterTrimFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = " ";
BadRequestException thrown =
@@ -315,6 +326,7 @@
public void createCheckerWithNonExistingRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = "non-existing";
UnprocessableEntityException thrown =
@@ -326,6 +338,7 @@
public void createDisabledChecker() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.status = CheckerStatus.DISABLED;
@@ -337,6 +350,7 @@
public void createCheckerWithBlockingConditions() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.blocking = ImmutableSet.of(BlockingCondition.STATE_NOT_PASSING);
@@ -348,6 +362,7 @@
public void createCheckerWithQuery() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = "f:foo";
@@ -359,6 +374,7 @@
public void createCheckerWithEmptyQuery() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = "";
@@ -370,6 +386,7 @@
public void createCheckerWithEmptyQueryAfterTrim() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = " ";
@@ -381,6 +398,7 @@
public void createCheckerWithUnsupportedOperatorInQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.QUERY_WITH_UNSUPPORTED_OPERATOR;
@@ -395,6 +413,7 @@
public void createCheckerWithInvalidQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.INVALID_QUERY;
@@ -407,6 +426,7 @@
public void createCheckerWithTooLongQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
+ input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.longQueryWithSupportedOperators(MAX_INDEX_TERMS * 2);
assertThat(CheckerQuery.clean(input.query)).isEqualTo(input.query);
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
index cb3f695..3f1f132 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
@@ -255,6 +255,16 @@
}
@Test
+ public void getCheckerWithMissingNameFails() throws Exception {
+ CheckerUuid checkerUuid = checkerOperations.newChecker().create();
+ checkerOperations.checker(checkerUuid).forInvalidation().unsetName().invalidate();
+
+ RestApiException thrown =
+ assertThrows(RestApiException.class, () -> getCheckerInfo(checkerUuid));
+ assertThat(thrown).hasMessageThat().contains("Cannot retrieve checker " + checkerUuid);
+ }
+
+ @Test
public void getCheckerWithMissingRepositoryFails() throws Exception {
CheckerUuid checkerUuid = checkerOperations.newChecker().create();
checkerOperations.checker(checkerUuid).forInvalidation().unsetRepository().invalidate();
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
index 590f82f..b41d9e8 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
@@ -89,6 +89,7 @@
CheckerUuid invalidCheckerUuid5 = checkerOperations.newChecker().create();
CheckerUuid invalidCheckerUuid6 = checkerOperations.newChecker().create();
CheckerUuid invalidCheckerUuid7 = checkerOperations.newChecker().create();
+ CheckerUuid invalidCheckerUuid8 = checkerOperations.newChecker().create();
checkerOperations
.checker(invalidCheckerUuid1)
.forInvalidation()
@@ -102,8 +103,9 @@
.invalidate();
checkerOperations.checker(invalidCheckerUuid4).forInvalidation().invalidStatus().invalidate();
checkerOperations.checker(invalidCheckerUuid5).forInvalidation().unsetUuid().invalidate();
- checkerOperations.checker(invalidCheckerUuid6).forInvalidation().unsetRepository().invalidate();
- checkerOperations.checker(invalidCheckerUuid7).forInvalidation().unsetStatus().invalidate();
+ checkerOperations.checker(invalidCheckerUuid6).forInvalidation().unsetName().invalidate();
+ checkerOperations.checker(invalidCheckerUuid7).forInvalidation().unsetRepository().invalidate();
+ checkerOperations.checker(invalidCheckerUuid8).forInvalidation().unsetStatus().invalidate();
List<CheckerInfo> allCheckers = checkersApi.all();
assertThat(allCheckers).containsExactly(checkerOperations.checker(checkerUuid).asInfo());
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListChecksIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListChecksIT.java
index 9650784..816ff5c 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListChecksIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListChecksIT.java
@@ -77,7 +77,10 @@
String checkerName1 = "Checker One";
CheckerUuid checkerUuid1 =
checkerOperations.newChecker().name(checkerName1).repository(project).create();
- CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();
+
+ String checkerName2 = "Checker Two";
+ CheckerUuid checkerUuid2 =
+ checkerOperations.newChecker().name(checkerName2).repository(project).create();
CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1);
checkOperations.newCheck(checkKey1).state(CheckState.RUNNING).upsert();
@@ -93,6 +96,7 @@
CheckInfo expectedCheckInfo2 = checkOperations.check(checkKey2).asInfo();
expectedCheckInfo2.repository = project.get();
+ expectedCheckInfo2.checkerName = checkerName2;
expectedCheckInfo2.blocking = ImmutableSet.of();
expectedCheckInfo2.checkerStatus = CheckerStatus.ENABLED;
@@ -105,7 +109,10 @@
String checkerName1 = "Checker One";
CheckerUuid checkerUuid1 =
checkerOperations.newChecker().name(checkerName1).repository(project).create();
- CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(project).create();
+
+ String checkerName2 = "Checker Two";
+ CheckerUuid checkerUuid2 =
+ checkerOperations.newChecker().name(checkerName2).repository(project).create();
CheckKey checkKey1 = CheckKey.create(project, patchSetId, checkerUuid1);
checkOperations.newCheck(checkKey1).state(CheckState.RUNNING).upsert();
@@ -121,6 +128,7 @@
CheckInfo expectedCheckInfo2 = checkOperations.check(checkKey2).asInfo();
expectedCheckInfo2.repository = project.get();
+ expectedCheckInfo2.checkerName = checkerName2;
expectedCheckInfo2.blocking = ImmutableSet.of();
expectedCheckInfo2.checkerStatus = CheckerStatus.ENABLED;
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java b/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
index f78fee2..8a2d2d4 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
@@ -70,7 +70,7 @@
CheckerInfo foundChecker = getCheckerFromServer(checkerUuid);
assertThat(foundChecker.uuid).isEqualTo(checkerUuid.get());
- assertThat(foundChecker.name).isNull();
+ assertThat(foundChecker.name).isNotNull();
assertThat(foundChecker.repository).isEqualTo(allProjects.get());
assertThat(foundChecker.status).isEqualTo(CheckerStatus.ENABLED);
assertThat(foundChecker.query).isEqualTo("status:open");
@@ -257,9 +257,9 @@
CheckerUuid checkerUuid =
checkerOperations.newChecker().name("ABC-789-this-name-must-be-unique").create();
- Optional<String> checkerName = checkerOperations.checker(checkerUuid).get().getName();
+ String checkerName = checkerOperations.checker(checkerUuid).get().getName();
- assertThat(checkerName).hasValue("ABC-789-this-name-must-be-unique");
+ assertThat(checkerName).isEqualTo("ABC-789-this-name-must-be-unique");
}
@Test
@@ -416,8 +416,8 @@
checkerOperations.checker(checkerUuid).forUpdate().name("updated name").update();
- Optional<String> currentName = checkerOperations.checker(checkerUuid).get().getName();
- assertThat(currentName).hasValue("updated name");
+ String currentName = checkerOperations.checker(checkerUuid).get().getName();
+ assertThat(currentName).isEqualTo("updated name");
}
@Test
@@ -591,6 +591,17 @@
}
@Test
+ public void nameCanBeUnset() throws Exception {
+ CheckerUuid checkerUuid = checkerOperations.newChecker().create();
+
+ checkerOperations.checker(checkerUuid).forInvalidation().unsetName().invalidate();
+
+ ConfigInvalidException thrown =
+ assertThrows(ConfigInvalidException.class, () -> checkers.getChecker(checkerUuid));
+ assertThat(thrown).hasMessageThat().contains("checker.name is not set in config file");
+ }
+
+ @Test
public void repositoryCanBeUnset() throws Exception {
CheckerUuid checkerUuid = checkerOperations.newChecker().create();
@@ -670,7 +681,7 @@
Checker checker = checkerOperations.checker(checkerUuid).get();
CheckerInfo checkerInfo = checkerOperations.checker(checkerUuid).asInfo();
assertThat(checkerInfo.uuid).isEqualTo(checker.getUuid().get());
- assertThat(checkerInfo.name).isEqualTo(checker.getName().get());
+ assertThat(checkerInfo.name).isEqualTo(checker.getName());
assertThat(checkerInfo.description).isEqualTo(checker.getDescription().get());
assertThat(checkerInfo.url).isEqualTo(checker.getUrl().get());
assertThat(checkerInfo.created).isEqualTo(checker.getCreated());
@@ -734,6 +745,7 @@
private CheckerInput createArbitraryCheckerInput() {
CheckerInput checkerInput = new CheckerInput();
checkerInput.uuid = "test:my-checker";
+ checkerInput.name = "My Checker";
checkerInput.repository = allProjects.get();
return checkerInput;
}
diff --git a/javatests/com/google/gerrit/plugins/checks/db/CheckerConfigTest.java b/javatests/com/google/gerrit/plugins/checks/db/CheckerConfigTest.java
index 15b85fe..a4d02b1 100644
--- a/javatests/com/google/gerrit/plugins/checks/db/CheckerConfigTest.java
+++ b/javatests/com/google/gerrit/plugins/checks/db/CheckerConfigTest.java
@@ -52,6 +52,7 @@
private TestRepository<?> testRepository;
private final CheckerUuid checkerUuid = CheckerUuid.parse("test:my-checker");
+ private final String checkerName = "My Checker";
private final Project.NameKey checkerRepository = Project.nameKey("my-repo");
private final TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
@@ -82,23 +83,52 @@
}
@Test
- public void setNameDuringCreation() throws Exception {
- String anotherName = "another-name";
+ public void specifiedCheckerNameIsRespectedForNewChecker() throws Exception {
+ CheckerCreation checkerCreation =
+ getPrefilledCheckerCreationBuilder().setName(checkerName).build();
+ createChecker(checkerCreation);
- CheckerCreation checkerCreation = getPrefilledCheckerCreationBuilder().build();
+ CheckerConfig checkerConfig = loadChecker(checkerUuid);
+ assertThat(checkerConfig).hasName(checkerName);
+ assertThat(checkerConfig).configStringList("name").containsExactly("My Checker");
+ }
+
+ @Test
+ public void nameOfCheckerUpdateOverridesCheckerCreation() throws Exception {
+ String anotherName = "Another Name";
+
+ CheckerCreation checkerCreation =
+ getPrefilledCheckerCreationBuilder().setName(checkerName).build();
CheckerUpdate checkerUpdate = CheckerUpdate.builder().setName(anotherName).build();
createChecker(checkerCreation, checkerUpdate);
CheckerConfig checkerConfig = loadChecker(checkerCreation.getCheckerUuid());
- assertThat(checkerConfig).hasNameThat().value().isEqualTo(anotherName);
+ assertThat(checkerConfig).hasName(anotherName);
assertThat(checkerConfig).configStringList("name").containsExactly(anotherName);
}
@Test
+ public void nameOfNewCheckerMustNotBeEmpty() throws Exception {
+ CheckerCreation checkerCreation =
+ getPrefilledCheckerCreationBuilder().setName("").buildWithoutValidationForTesting();
+ CheckerConfig checkerConfig =
+ CheckerConfig.createForNewChecker(projectName, repository, checkerCreation);
+
+ try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
+ Throwable thrown = assertThrows(Throwable.class, () -> checkerConfig.commit(metaDataUpdate));
+ assertThat(thrown).hasCauseThat().isInstanceOf(ConfigInvalidException.class);
+ assertThat(thrown)
+ .hasMessageThat()
+ .contains(String.format("Name of the checker %s must be defined", checkerUuid));
+ }
+ }
+
+ @Test
public void descriptionDefaultsToOptionalEmpty() throws Exception {
CheckerCreation checkerCreation =
CheckerCreation.builder()
.setCheckerUuid(checkerUuid)
+ .setName(checkerName)
.setRepository(checkerRepository)
.build();
createChecker(checkerCreation);
@@ -137,6 +167,7 @@
CheckerCreation checkerCreation =
CheckerCreation.builder()
.setCheckerUuid(checkerUuid)
+ .setName(checkerName)
.setRepository(checkerRepository)
.build();
createChecker(checkerCreation);
@@ -202,7 +233,9 @@
@Test
public void repositoryOfNewCheckerMustNotBeEmpty() throws Exception {
CheckerCreation checkerCreation =
- getPrefilledCheckerCreationBuilder().setRepository(Project.nameKey("")).build();
+ getPrefilledCheckerCreationBuilder()
+ .setRepository(Project.nameKey(""))
+ .buildWithoutValidationForTesting();
CheckerConfig checkerConfig =
CheckerConfig.createForNewChecker(projectName, repository, checkerCreation);
@@ -237,6 +270,23 @@
}
@Test
+ public void nameInConfigMayNotBeUndefined() throws Exception {
+ populateCheckerConfig(
+ checkerUuid,
+ "[checker]\n uuid = "
+ + checkerUuid
+ + "\n repository = "
+ + checkerRepository
+ + "\n status = ENABLED");
+
+ ConfigInvalidException thrown =
+ assertThrows(ConfigInvalidException.class, () -> loadChecker(checkerUuid));
+ assertThat(thrown)
+ .hasMessageThat()
+ .contains("checker.name is not set in config file for checker " + checkerUuid);
+ }
+
+ @Test
public void correctCommitMessageForCheckerUpdate() throws Exception {
createArbitraryChecker(checkerUuid);
assertThatCommitMessage(checkerUuid).isEqualTo("Create checker");
@@ -247,31 +297,39 @@
}
@Test
- public void nameCanBeUpdatedAndRemoved() throws Exception {
+ public void nameCanBeUpdated() throws Exception {
CheckerCreation checkerCreation =
CheckerCreation.builder()
.setCheckerUuid(checkerUuid)
+ .setName(checkerName)
.setRepository(checkerRepository)
.build();
createChecker(checkerCreation);
CheckerConfig checkerConfig = loadChecker(checkerUuid);
- assertThat(checkerConfig).hasNameThat().isAbsent();
+ assertThat(checkerConfig).hasName(checkerName);
- String newName = "new-name";
+ String newName = "New Name";
CheckerUpdate checkerUpdate = CheckerUpdate.builder().setName(newName).build();
updateChecker(checkerUuid, checkerUpdate);
checkerConfig = loadChecker(checkerUuid);
- assertThat(checkerConfig).hasNameThat().value().isEqualTo(newName);
+ assertThat(checkerConfig).hasName(newName);
assertThat(checkerConfig).configStringList("name").containsExactly(newName);
+ }
- checkerUpdate = CheckerUpdate.builder().setName("").build();
- updateChecker(checkerUuid, checkerUpdate);
+ @Test
+ public void nameCannotBeRemoved() throws Exception {
+ createArbitraryChecker(checkerUuid);
- checkerConfig = loadChecker(checkerUuid);
- assertThat(checkerConfig).hasNameThat().isAbsent();
- assertThat(checkerConfig).configStringList("name").isEmpty();
+ CheckerUpdate checkerUpdate =
+ CheckerUpdate.builder().setName("").buildWithoutValidationForTesting();
+
+ IOException thrown =
+ assertThrows(IOException.class, () -> updateChecker(checkerUuid, checkerUpdate));
+ assertThat(thrown)
+ .hasMessageThat()
+ .contains(String.format("Name of the checker %s must be defined", checkerUuid));
}
@Test
@@ -325,6 +383,7 @@
CheckerCreation checkerCreation =
CheckerCreation.builder()
.setCheckerUuid(checkerUuid)
+ .setName(checkerName)
.setRepository(checkerRepository)
.build();
createChecker(checkerCreation);
@@ -345,7 +404,9 @@
createArbitraryChecker(checkerUuid);
CheckerUpdate checkerUpdate =
- CheckerUpdate.builder().setRepository(Project.nameKey("")).build();
+ CheckerUpdate.builder()
+ .setRepository(Project.nameKey(""))
+ .buildWithoutValidationForTesting();
IOException thrown =
assertThrows(IOException.class, () -> updateChecker(checkerUuid, checkerUpdate));
@@ -514,7 +575,10 @@
}
private CheckerCreation.Builder getPrefilledCheckerCreationBuilder() {
- return CheckerCreation.builder().setCheckerUuid(checkerUuid).setRepository(checkerRepository);
+ return CheckerCreation.builder()
+ .setCheckerUuid(checkerUuid)
+ .setName(checkerName)
+ .setRepository(checkerRepository);
}
private CheckerConfig createChecker(CheckerCreation checkerCreation) throws Exception {