Repository: ambari Updated Branches: refs/heads/trunk 03e04a684 -> 50ee0ff6a
AMBARI-5438 Add unit tests to configuration and update controllers. (atkach) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/50ee0ff6 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/50ee0ff6 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/50ee0ff6 Branch: refs/heads/trunk Commit: 50ee0ff6aacfaeee971606b1b1be50af722b47ed Parents: 03e04a6 Author: atkach <atk...@hortonworks.com> Authored: Fri Apr 11 14:05:18 2014 +0300 Committer: atkach <atk...@hortonworks.com> Committed: Fri Apr 11 14:05:18 2014 +0300 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 2 + .../controllers/global/cluster_controller.js | 3 +- .../global/configuration_controller.js | 2 - .../app/controllers/global/update_controller.js | 127 ++++----- .../global/configuration_controller_test.js | 134 ++++++++++ .../global/update_controller_test.js | 259 +++++++++++++++++++ 6 files changed, 462 insertions(+), 65 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/app/assets/test/tests.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js index 4390c02..40f1e25 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -23,6 +23,8 @@ require('test/app_test'); require('test/data/HDP2/site_properties_test'); require('test/controllers/global/background_operations_test'); require('test/controllers/global/cluster_controller_test'); +require('test/controllers/global/update_controller_test'); +require('test/controllers/global/configuration_controller_test'); require('test/controllers/main/app_contoller_test'); require('test/controllers/main/admin/cluster_test'); require('test/controllers/main/admin/security/add/addSecurity_controller_test'); http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/app/controllers/global/cluster_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js index 7bea318..657b7a1 100644 --- a/ambari-web/app/controllers/global/cluster_controller.js +++ b/ambari-web/app/controllers/global/cluster_controller.js @@ -353,8 +353,7 @@ App.ClusterController = Em.Controller.extend({ self.updateLoadStatus('componentConfigs'); } }, true); - App.router.get('updateController').updateServiceMetric(function () { - }, true); + App.router.get('updateController').updateServiceMetric(function () {}); }); }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/app/controllers/global/configuration_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/configuration_controller.js b/ambari-web/app/controllers/global/configuration_controller.js index 5aa410d..3e01572 100644 --- a/ambari-web/app/controllers/global/configuration_controller.js +++ b/ambari-web/app/controllers/global/configuration_controller.js @@ -80,6 +80,4 @@ App.ConfigurationController = Em.Controller.extend({ App.db.setConfigs(storedConfigs); return loadedConfigs; } - - }); http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/app/controllers/global/update_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js index 227b4ee..66f6dea 100644 --- a/ambari-web/app/controllers/global/update_controller.js +++ b/ambari-web/app/controllers/global/update_controller.js @@ -19,24 +19,27 @@ var App = require('app'); App.UpdateController = Em.Controller.extend({ - name:'updateController', - isUpdated:false, - cluster:null, + name: 'updateController', + isUpdated: false, + cluster: null, isWorking: false, timeIntervalId: null, - clusterName:function () { + clusterName: function () { return App.router.get('clusterController.clusterName'); }.property('App.router.clusterController.clusterName'), + location: function () { + return App.router.get('location.lastSetURL'); + }.property('App.router.location.lastSetURL'), - getUrl:function (testUrl, url) { + getUrl: function (testUrl, url) { return (App.testMode) ? testUrl : App.apiPrefix + '/clusters/' + this.get('clusterName') + url; }, /** * Start polling, when <code>isWorking</code> become true */ - updateAll:function(){ - if(this.get('isWorking')) { + updateAll: function () { + if (this.get('isWorking')) { App.updater.run(this, 'updateServices', 'isWorking'); App.updater.run(this, 'updateHostConditionally', 'isWorking'); App.updater.run(this, 'updateServiceMetricConditionally', 'isWorking', App.componentsUpdateInterval); @@ -55,8 +58,7 @@ App.UpdateController = Em.Controller.extend({ * @param callback */ updateHostConditionally: function (callback) { - var location = App.router.get('location.lastSetURL'); - if (/\/main\/(hosts|charts\/heatmap).*/.test(location)) { + if (/\/main\/(hosts|charts\/heatmap).*/.test(this.get('location'))) { this.updateHost(callback); } else { callback(); @@ -69,19 +71,18 @@ App.UpdateController = Em.Controller.extend({ * /main/services/* * @param callback */ - updateServiceMetricConditionally: function(callback){ - var location = App.router.get('location.lastSetURL'); - if (/\/main\/(dashboard|services).*/.test(location)) { + updateServiceMetricConditionally: function (callback) { + if (/\/main\/(dashboard|services).*/.test(this.get('location'))) { this.updateServiceMetric(callback); } else { callback(); } }, - updateHost:function(callback) { + updateHost: function (callback) { var testUrl = App.get('isHadoop2Stack') ? '/data/hosts/HDP2/hosts.json' : '/data/hosts/hosts.json'; var hostsUrl = this.getUrl(testUrl, '/hosts?fields=Hosts/host_name,Hosts/host_status,Hosts/last_heartbeat_time,Hosts/disk_info,Hosts/maintenance_state,' + - 'metrics/disk,metrics/load/load_one,metrics/cpu/cpu_system,metrics/cpu/cpu_user,metrics/memory/mem_total,metrics/memory/mem_free'+ + 'metrics/disk,metrics/load/load_one,metrics/cpu/cpu_system,metrics/cpu/cpu_user,metrics/memory/mem_total,metrics/memory/mem_free' + '&minimal_response=true'); App.HttpClient.get(hostsUrl, App.hostsMapper, { complete: callback @@ -89,64 +90,35 @@ App.UpdateController = Em.Controller.extend({ }, graphs: [], graphsUpdate: function (callback) { - var existedGraphs = []; - this.get('graphs').forEach(function (_graph) { - var view = Em.View.views[_graph.id]; - if (view) { - existedGraphs.push(_graph); - //console.log('updated graph', _graph.name); + var existedGraphs = []; + this.get('graphs').forEach(function (_graph) { + var view = Em.View.views[_graph.id]; + if (view) { + existedGraphs.push(_graph); + //console.log('updated graph', _graph.name); + view.loadData(); + //if graph opened as modal popup update it to + if ($(".modal-graph-line .modal-body #" + _graph.popupId + "-container-popup").length) { view.loadData(); - //if graph opened as modal popup update it to - if($(".modal-graph-line .modal-body #" + _graph.popupId + "-container-popup").length) { - view.loadData(); - } } - }); + } + }); callback(); this.set('graphs', existedGraphs); }, /** - * Updates the services information. + * Updates the services information. * * @param callback - * @param isInitialLoad If true, only basic information is loaded. */ - updateServiceMetric: function (callback, isInitialLoad) { + updateServiceMetric: function (callback) { var self = this; self.set('isUpdated', false); - var conditionalFields = []; - var initialFields = []; - var serviceSpecificParams = { - 'FLUME': "host_components/metrics/flume/flume", - 'YARN': "host_components/metrics/yarn/Queue," + - "ServiceComponentInfo/rm_metrics/cluster/activeNMcount," + - "ServiceComponentInfo/rm_metrics/cluster/unhealthyNMcount," + - "ServiceComponentInfo/rm_metrics/cluster/rebootedNMcount," + - "ServiceComponentInfo/rm_metrics/cluster/decommissionedNMcount", - 'HBASE': "host_components/metrics/hbase/master/IsActiveMaster," + - "ServiceComponentInfo/MasterStartTime," + - "ServiceComponentInfo/MasterActiveTime," + - "ServiceComponentInfo/AverageLoad," + - "ServiceComponentInfo/Revision," + - "ServiceComponentInfo/RegionsInTransition", - 'MAPREDUCE': "ServiceComponentInfo/AliveNodes," + - "ServiceComponentInfo/GrayListedNodes," + - "ServiceComponentInfo/BlackListedNodes," + - "ServiceComponentInfo/jobtracker/*,", - 'STORM': "metrics/api/cluster/summary," - }; - var services = App.cache['services']; - services.forEach(function (service) { - var urlParams = serviceSpecificParams[service.ServiceInfo.service_name]; - if (urlParams) { - conditionalFields.push(urlParams); - } - }); + var conditionalFields = this.getConditionalFields(); var conditionalFieldsString = conditionalFields.length > 0 ? ',' + conditionalFields.join(',') : ''; - var initialFieldsString = initialFields.length > 0 ? ',' + initialFields.join(',') : ''; - var testUrl = App.get('isHadoop2Stack') ? '/data/dashboard/HDP2/master_components.json':'/data/dashboard/services.json'; + var testUrl = App.get('isHadoop2Stack') ? '/data/dashboard/HDP2/master_components.json' : '/data/dashboard/services.json'; var realUrl = '/components/?ServiceComponentInfo/category=MASTER&fields=' + 'ServiceComponentInfo/Version,' + @@ -175,16 +147,50 @@ App.UpdateController = Em.Controller.extend({ conditionalFieldsString + '&minimal_response=true'; - var servicesUrl = isInitialLoad ? this.getUrl(testUrl, realUrl + initialFieldsString) : this.getUrl(testUrl, realUrl); + var servicesUrl = this.getUrl(testUrl, realUrl); callback = callback || function () { self.set('isUpdated', true); }; App.HttpClient.get(servicesUrl, App.serviceMetricsMapper, { - complete: function(){ + complete: function () { callback(); } }); }, + /** + * construct conditional parameters of query, depending on which services are installed + * @return {Array} + */ + getConditionalFields: function () { + var conditionalFields = []; + var serviceSpecificParams = { + 'FLUME': "host_components/metrics/flume/flume", + 'YARN': "host_components/metrics/yarn/Queue," + + "ServiceComponentInfo/rm_metrics/cluster/activeNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/unhealthyNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/rebootedNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/decommissionedNMcount", + 'HBASE': "host_components/metrics/hbase/master/IsActiveMaster," + + "ServiceComponentInfo/MasterStartTime," + + "ServiceComponentInfo/MasterActiveTime," + + "ServiceComponentInfo/AverageLoad," + + "ServiceComponentInfo/Revision," + + "ServiceComponentInfo/RegionsInTransition", + 'MAPREDUCE': "ServiceComponentInfo/AliveNodes," + + "ServiceComponentInfo/GrayListedNodes," + + "ServiceComponentInfo/BlackListedNodes," + + "ServiceComponentInfo/jobtracker/*,", + 'STORM': "metrics/api/cluster/summary," + }; + var services = App.cache['services']; + services.forEach(function (service) { + var urlParams = serviceSpecificParams[service.ServiceInfo.service_name]; + if (urlParams) { + conditionalFields.push(urlParams); + } + }); + return conditionalFields; + }, updateServices: function (callback) { var testUrl = '/data/services/HDP2/services.json'; var componentConfigUrl = this.getUrl(testUrl, '/services?fields=alerts/summary,ServiceInfo/state,ServiceInfo/maintenance_state&minimal_response=true'); @@ -199,5 +205,4 @@ App.UpdateController = Em.Controller.extend({ complete: callback }); } - }); http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/test/controllers/global/configuration_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/configuration_controller_test.js b/ambari-web/test/controllers/global/configuration_controller_test.js new file mode 100644 index 0000000..5baac0e --- /dev/null +++ b/ambari-web/test/controllers/global/configuration_controller_test.js @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + + +var App = require('app'); +require('controllers/global/configuration_controller'); + + +describe('App.ConfigurationController', function () { + var controller = App.ConfigurationController.create(); + + describe('#checkTagsChanges()', function () { + var testCases = [ + { + title: 'Tags haven\'t been uploaded', + content: { + tags: [], + storedTags: [] + }, + result: false + }, + { + title: 'New tag uploaded', + content: { + tags: [ + { + siteName: 'site1', + tagName: 1 + } + ], + storedTags: [] + }, + result: true + }, + { + title: 'Existing tag with with new tagName', + content: { + tags: [ + { + siteName: 'site1', + tagName: 1 + } + ], + storedTags: [ + { + siteName: 'site1', + tagName: 2 + } + ] + }, + result: true + }, + { + title: 'Tags with different tagNames', + content: { + tags: [ + { + siteName: 'site1', + tagName: 1 + } + ], + storedTags: [ + { + siteName: 'site2', + tagName: 1 + } + ] + }, + result: true + }, + { + title: 'One new tag uploaded', + content: { + tags: [ + { + siteName: 'site2', + tagName: 1 + }, + { + siteName: 'site1', + tagName: 1 + } + ], + storedTags: [ + { + siteName: 'site2', + tagName: 1 + } + ] + }, + result: true + }, + { + title: 'Tags haven\'t been changed', + content: { + tags: [ + { + siteName: 'site2', + tagName: 1 + } + ], + storedTags: [ + { + siteName: 'site2', + tagName: 1 + } + ] + }, + result: false + } + ]; + + testCases.forEach(function (test) { + it(test.title, function () { + expect(controller.checkTagsChanges(test.content.tags, test.content.storedTags)).to.equal(test.result); + }); + }); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/50ee0ff6/ambari-web/test/controllers/global/update_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/update_controller_test.js b/ambari-web/test/controllers/global/update_controller_test.js new file mode 100644 index 0000000..79374c5 --- /dev/null +++ b/ambari-web/test/controllers/global/update_controller_test.js @@ -0,0 +1,259 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + + +var App = require('app'); +require('controllers/global/update_controller'); + + +describe('App.UpdateController', function () { + var controller = App.UpdateController.create({ + clusterName: '', + location: '', + updateServiceMetric: function(){} + }); + + describe('#getUrl()', function () { + + it('testMode = true', function () { + App.set('testMode', true); + expect(controller.getUrl('test', '/real')).to.equal('test'); + }); + + it('testMode = false', function () { + App.set('testMode', false); + expect(controller.getUrl('test', '/real')).to.equal('/api/v1/clusters//real'); + }); + + it('testMode = false', function () { + App.set('testMode', false); + controller.set('clusterName', 'mycluster'); + expect(controller.getUrl('test', '/real')).to.equal('/api/v1/clusters/mycluster/real'); + }); + }); + + describe('#updateAll()', function () { + + beforeEach(function () { + sinon.spy(App.updater, 'run'); + }); + afterEach(function () { + App.updater.run.restore(); + }); + it('isWorking = false', function () { + controller.set('isWorking', false); + expect(App.updater.run.called).to.equal(false); + }); + + it('isWorking = true, App.supports.hostOverrides = false', function () { + App.supports.hostOverrides = false; + controller.set('isWorking', true); + expect(App.updater.run.callCount).to.equal(4); + controller.set('isWorking', false); + }); + + it('isWorking = true, App.supports.hostOverrides = true', function () { + App.supports.hostOverrides = true; + controller.set('isWorking', true); + expect(App.updater.run.callCount).to.equal(5); + }); + }); + + describe('#updateHostConditionally()', function () { + var context = { + callback: function(){} + }; + + beforeEach(function () { + sinon.spy(controller, 'updateHost'); + sinon.spy(context, 'callback'); + }); + afterEach(function () { + controller.updateHost.restore(); + context.callback.restore(); + }); + + it('location is empty', function () { + controller.set('location', ''); + controller.updateHostConditionally(context.callback); + expect(controller.updateHost.called).to.equal(false); + expect(context.callback.called).to.equal(true); + }); + it('location is "/main/dashboard"', function () { + controller.set('location', '/main/dashboard'); + controller.updateHostConditionally(context.callback); + expect(controller.updateHost.called).to.equal(false); + expect(context.callback.called).to.equal(true); + }); + it('location is "/main/hosts"', function () { + controller.set('location', '/main/hosts'); + controller.updateHostConditionally(context.callback); + expect(controller.updateHost.called).to.equal(true); + expect(context.callback.called).to.equal(false); + }); + it('location is "/main/charts/heatmap"', function () { + controller.set('location', '/main/charts/heatmap'); + controller.updateHostConditionally(context.callback); + expect(controller.updateHost.called).to.equal(true); + expect(context.callback.called).to.equal(false); + }); + it('location is "/main/hosts/host1"', function () { + controller.set('location', '/main/hosts/host1'); + controller.updateHostConditionally(context.callback); + expect(controller.updateHost.called).to.equal(true); + expect(context.callback.called).to.equal(false); + }); + }); + + describe('#updateServiceMetricConditionally()', function () { + var context = { + callback: function(){} + }; + + beforeEach(function () { + sinon.spy(controller, 'updateServiceMetric'); + sinon.spy(context, 'callback'); + }); + afterEach(function () { + controller.updateServiceMetric.restore(); + context.callback.restore(); + }); + + it('location is empty', function () { + controller.set('location', ''); + controller.updateServiceMetricConditionally(context.callback); + expect(controller.updateServiceMetric.called).to.equal(false); + expect(context.callback.called).to.equal(true); + }); + it('location is "/main/hosts"', function () { + controller.set('location', '/main/hosts'); + controller.updateServiceMetricConditionally(context.callback); + expect(controller.updateServiceMetric.called).to.equal(false); + expect(context.callback.called).to.equal(true); + }); + it('location is "/main/dashboard"', function () { + controller.set('location', '/main/dashboard'); + controller.updateServiceMetricConditionally(context.callback); + expect(controller.updateServiceMetric.called).to.equal(true); + expect(context.callback.called).to.equal(false); + }); + it('location is "/main/services/HDFS"', function () { + controller.set('location', '/main/services/HDFS'); + controller.updateServiceMetricConditionally(context.callback); + expect(controller.updateServiceMetric.called).to.equal(true); + expect(context.callback.called).to.equal(false); + }); + }); + + + describe('#getConditionalFields()', function () { + + var testCases = [ + { + title: 'No services exist', + services: [], + result: [] + }, + { + title: 'HDFS service', + services: [ + { + ServiceInfo: { + service_name: 'HDFS' + } + } + ], + result: [] + }, + { + title: 'FLUME service', + services: [ + { + ServiceInfo: { + service_name: 'FLUME' + } + } + ], + result: ["host_components/metrics/flume/flume"] + }, + { + title: 'YARN service', + services: [ + { + ServiceInfo: { + service_name: 'YARN' + } + } + ], + result: ["host_components/metrics/yarn/Queue," + + "ServiceComponentInfo/rm_metrics/cluster/activeNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/unhealthyNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/rebootedNMcount," + + "ServiceComponentInfo/rm_metrics/cluster/decommissionedNMcount"] + }, + { + title: 'HBASE service', + services: [ + { + ServiceInfo: { + service_name: 'HBASE' + } + } + ], + result: ["host_components/metrics/hbase/master/IsActiveMaster," + + "ServiceComponentInfo/MasterStartTime," + + "ServiceComponentInfo/MasterActiveTime," + + "ServiceComponentInfo/AverageLoad," + + "ServiceComponentInfo/Revision," + + "ServiceComponentInfo/RegionsInTransition"] + }, + { + title: 'MAPREDUCE service', + services: [ + { + ServiceInfo: { + service_name: 'MAPREDUCE' + } + } + ], + result: ["ServiceComponentInfo/AliveNodes," + + "ServiceComponentInfo/GrayListedNodes," + + "ServiceComponentInfo/BlackListedNodes," + + "ServiceComponentInfo/jobtracker/*,"] + }, + { + title: 'STORM service', + services: [ + { + ServiceInfo: { + service_name: 'STORM' + } + } + ], + result: ["metrics/api/cluster/summary,"] + } + ]; + + testCases.forEach(function(test){ + it(test.title, function () { + App.cache['services'] = test.services; + expect(controller.getConditionalFields()).to.eql(test.result); + }); + }); + }); +}); \ No newline at end of file