You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2014/04/10 15:59:28 UTC

git commit: AMBARI-5422 UI unit tests for cluster and BO controller. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk f71d6b923 -> cc92b6102


AMBARI-5422 UI unit tests for cluster and BO controller. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/cc92b610
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/cc92b610
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/cc92b610

Branch: refs/heads/trunk
Commit: cc92b610264bfca23bbdd9730a4972ccb1848b70
Parents: f71d6b9
Author: atkach <at...@hortonworks.com>
Authored: Thu Apr 10 16:57:11 2014 +0300
Committer: atkach <at...@hortonworks.com>
Committed: Thu Apr 10 16:59:27 2014 +0300

----------------------------------------------------------------------
 .../global/background_operations_controller.js  |  77 ++-
 .../controllers/global/cluster_controller.js    |  35 +-
 ambari-web/app/utils/host_progress_popup.js     |  11 +-
 .../global/background_operations_test.js        | 691 ++++++++++++++++---
 .../global/cluster_controller_test.js           | 394 ++++++++++-
 .../test/controllers/main/admin/cluster_test.js |  40 +-
 6 files changed, 1079 insertions(+), 169 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/ambari-web/app/controllers/global/background_operations_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/background_operations_controller.js b/ambari-web/app/controllers/global/background_operations_controller.js
index 9dee2c0..933a413 100644
--- a/ambari-web/app/controllers/global/background_operations_controller.js
+++ b/ambari-web/app/controllers/global/background_operations_controller.js
@@ -165,27 +165,13 @@ App.BackgroundOperationsController = Em.Controller.extend({
    */
   callBackForMostRecent: function (data) {
     var runningServices = 0;
-    var self = this;
     var currentRequestIds = [];
 
     data.items.forEach(function (request) {
-      var rq = self.get("services").findProperty('id', request.Requests.id);
-      var isRunning = (request.Requests.task_count -
-        (request.Requests.aborted_task_count + request.Requests.completed_task_count + request.Requests.failed_task_count
-         + request.Requests.timed_out_task_count - request.Requests.queued_task_count)) > 0;
+      var rq = this.get("services").findProperty('id', request.Requests.id);
+      var isRunning = this.isRequestRunning(request);
       var requestParams = this.parseRequestContext(request.Requests.request_context);
-      var inputs = null;
-      if (request.Requests.inputs) {
-        inputs = JSON.parse(request.Requests.inputs);
-      }
-      var oneHost = false;
-      if (inputs && inputs.included_hosts) {
-        var hosts = inputs.included_hosts.split(',');
-        oneHost = (hosts.length < 2);
-      }
-      if(request.Requests.request_schedule && oneHost && /Recommission/.test(requestParams.requestContext)){
-        request.Requests.request_schedule.schedule_id = null;
-      }
+      this.assignScheduleId(request, requestParams);
       currentRequestIds.push(request.Requests.id);
       if (rq) {
         rq.set('progress', Math.ceil(request.Requests.progress_percent));
@@ -210,18 +196,61 @@ App.BackgroundOperationsController = Em.Controller.extend({
           previousTaskStatusMap: {},
           contextCommand: requestParams.contextCommand
         });
-        self.get("services").unshift(rq);
+        this.get("services").unshift(rq);
       }
       runningServices += ~~isRunning;
     }, this);
-    //remove old request if it's absent in API response
-    self.get('services').forEach(function(service, index, services){
-      if(!currentRequestIds.contains(service.id)) {
+    this.removeOldRequests(currentRequestIds);
+    this.set("allOperationsCount", runningServices);
+    this.set('serviceTimestamp', App.dateTime());
+  },
+  /**
+   * remove old requests
+   * as API returns 10 latest request, the requests that absent in response should be removed
+   * @param currentRequestIds
+   */
+  removeOldRequests: function (currentRequestIds) {
+    this.get('services').forEach(function (service, index, services) {
+      if (!currentRequestIds.contains(service.id)) {
         services.splice(index, 1);
       }
     });
-    self.set("allOperationsCount", runningServices);
-    self.set('serviceTimestamp', App.dateTime());
+  },
+  /**
+   * identify whether request is running by task counters
+   * @param request
+   * @return {Boolean}
+   */
+  isRequestRunning: function (request) {
+    return (request.Requests.task_count -
+      (request.Requests.aborted_task_count + request.Requests.completed_task_count + request.Requests.failed_task_count
+        + request.Requests.timed_out_task_count - request.Requests.queued_task_count)) > 0;
+  },
+  /**
+   * identify whether there is only one host in request
+   * @param inputs
+   * @return {Boolean}
+   */
+  isOneHost: function (inputs) {
+    if (!inputs) {
+      return false;
+    }
+    inputs = JSON.parse(inputs);
+    if (inputs && inputs.included_hosts) {
+      return inputs.included_hosts.split(',').length < 2;
+    }
+    return false
+  },
+  /**
+   * assign schedule_id of request to null if it's Recommision operation
+   * @param request
+   * @param requestParams
+   */
+  assignScheduleId: function (request, requestParams) {
+    var oneHost = this.isOneHost(request.Requests.inputs);
+    if (request.Requests.request_schedule && oneHost && /Recommission/.test(requestParams.requestContext)) {
+      request.Requests.request_schedule.schedule_id = null;
+    }
   },
 
   /**
@@ -328,4 +357,4 @@ App.BackgroundOperationsController.CommandContexts = {
    * @param {Number} totalBatchCount Parameter {2}. Total number of batches. Example 10.
    */
   ROLLING_RESTART : "_PARSE_.ROLLING-RESTART.{0}.{1}.{2}"
-}
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/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 242ba56..7bea318 100644
--- a/ambari-web/app/controllers/global/cluster_controller.js
+++ b/ambari-web/app/controllers/global/cluster_controller.js
@@ -52,15 +52,15 @@ App.ClusterController = Em.Controller.extend({
     this.set('clusterDataLoadedPercent', 'width:' + (Math.floor(numLoaded / loadListLength * 100)).toString() + '%');
   },
 
-  dataLoadList:Em.Object.create({
-    'hosts':false,
-    'serviceMetrics':false,
-    'stackComponents':false,
+  dataLoadList: Em.Object.create({
+    'hosts': false,
+    'serviceMetrics': false,
+    'stackComponents': false,
     'services': false,
-    'cluster':false,
-    'clusterStatus':false,
-    'racks':false,
-    'users':false,
+    'cluster': false,
+    'clusterStatus': false,
+    'racks': false,
+    'users': false,
     'componentConfigs': false
   }),
 
@@ -69,7 +69,7 @@ App.ClusterController = Em.Controller.extend({
    */
   loadClusterName: function (reload) {
     if (this.get('clusterName') && !reload) {
-      return;
+      return false;
     }
 
     App.ajax.send({
@@ -175,8 +175,7 @@ App.ClusterController = Em.Controller.extend({
       return 'http://nagiosserver/nagios';
     } else {
       // We want live data here
-      var svcs = App.Service.find();
-      var nagiosSvc = svcs.findProperty("serviceName", "NAGIOS");
+      var nagiosSvc = App.Service.find("NAGIOS");
       if (nagiosSvc) {
         var svcComponents = nagiosSvc.get('hostComponents');
         if (svcComponents) {
@@ -392,7 +391,7 @@ App.ClusterController = Em.Controller.extend({
     }, callback)
   },
 
-  loadAmbariViews: function() {
+  loadAmbariViews: function () {
     App.ajax.send({
       name: 'views.info',
       sender: this,
@@ -400,9 +399,9 @@ App.ClusterController = Em.Controller.extend({
     });
   },
 
-  loadAmbariViewsSuccess: function(data) {
-    this.set('ambariViews',[]);
-    data.items.forEach(function(item){
+  loadAmbariViewsSuccess: function (data) {
+    this.set('ambariViews', []);
+    data.items.forEach(function (item) {
       App.ajax.send({
         name: 'views.instances',
         data: {
@@ -414,8 +413,8 @@ App.ClusterController = Em.Controller.extend({
     }, this)
   },
 
-  loadViewInstancesSuccess: function(data) {
-    data.instances.forEach(function(instance){
+  loadViewInstancesSuccess: function (data) {
+    data.instances.forEach(function (instance) {
       var view = Em.Object.create({
         label: data.ViewInfo.label,
         viewName: instance.ViewInstanceInfo.view_name,
@@ -430,7 +429,7 @@ App.ClusterController = Em.Controller.extend({
    *
    * @param callback
    */
-  loadStackServiceComponents: function(callback) {
+  loadStackServiceComponents: function (callback) {
     var callbackObj = {
       loadStackServiceComponentsSuccess: callback
     };

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/ambari-web/app/utils/host_progress_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/host_progress_popup.js b/ambari-web/app/utils/host_progress_popup.js
index 8d1cdbe..290cbcf 100644
--- a/ambari-web/app/utils/host_progress_popup.js
+++ b/ambari-web/app/utils/host_progress_popup.js
@@ -158,15 +158,18 @@ App.HostPopup = Em.Object.create({
    * @return {Number} percent of completion
    */
   getProgress: function (tasks) {
+    if (!tasks || tasks.length === 0) return 0;
+
     var completedActions = 0;
     var queuedActions = 0;
     var inProgressActions = 0;
-    tasks.forEach(function(task) {
-      if(['COMPLETED', 'FAILED', 'ABORTED', 'TIMEDOUT'].contains(task.Tasks.status)){
+
+    tasks.forEach(function (task) {
+      if (['COMPLETED', 'FAILED', 'ABORTED', 'TIMEDOUT'].contains(task.Tasks.status)) {
         completedActions++;
-      } else if(task.Tasks.status === 'QUEUED'){
+      } else if (task.Tasks.status === 'QUEUED') {
         queuedActions++;
-      } else if(task.Tasks.status === 'IN_PROGRESS'){
+      } else if (task.Tasks.status === 'IN_PROGRESS') {
         inProgressActions++;
       }
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/ambari-web/test/controllers/global/background_operations_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/global/background_operations_test.js b/ambari-web/test/controllers/global/background_operations_test.js
index 710147a..23166ec 100644
--- a/ambari-web/test/controllers/global/background_operations_test.js
+++ b/ambari-web/test/controllers/global/background_operations_test.js
@@ -29,101 +29,100 @@ require('controllers/global/background_operations_controller');
 require('views/common/modal_popup');
 require('utils/host_progress_popup');
 
-var controller;
-
 describe('App.BackgroundOperationsController', function () {
 
-  /**
-   * Predefined data
-   *
-   */
-  App.set('clusterName', 'testName');
-  App.bgOperationsUpdateInterval = 100;
-
-  var tests = Em.A([
-    {
-      levelInfo: Em.Object.create({
-        name: 'REQUESTS_LIST',
-        requestId: null,
-        taskId: null,
-        sync: false
-      }),
-      e: {
-        name: 'background_operations.get_most_recent',
-        successCallback: 'callBackForMostRecent',
-        data: {}
-      },
-      response: {items:[]},
-      m: '"Get Most Recent"'
-    },
-    {
-      levelInfo: Em.Object.create({
-        name: 'TASK_DETAILS',
-        requestId: 1,
-        taskId: 1,
-        sync: false
-      }),
-      e: {
-        name: 'background_operations.get_by_task',
-        successCallback: 'callBackFilteredByTask',
-        data: {
-          taskId: 1,
-          requestId: 1,
+  var controller = App.BackgroundOperationsController.create();
+
+  describe('#getQueryParams', function () {
+    /**
+     * Predefined data
+     *
+     */
+    App.set('clusterName', 'testName');
+    App.bgOperationsUpdateInterval = 100;
+
+    var tests = Em.A([
+      {
+        levelInfo: Em.Object.create({
+          name: 'REQUESTS_LIST',
+          requestId: null,
+          taskId: null,
           sync: false
-        }
-      },
-      response: {items:{Tasks:{request_id:0}}},
-      m: '"Filtered By task"'
-    },
-    {
-      levelInfo: Em.Object.create({
-        name: 'TASKS_LIST',
-        requestId: 1,
-        taskId: 1,
-        sync: false
-      }),
-      e: {
-        name: 'background_operations.get_by_request',
-        successCallback: 'callBackFilteredByRequest',
-        data: {
+        }),
+        e: {
+          name: 'background_operations.get_most_recent',
+          successCallback: 'callBackForMostRecent',
+          data: {}
+        },
+        response: {items: []},
+        m: '"Get Most Recent"'
+      },
+      {
+        levelInfo: Em.Object.create({
+          name: 'TASK_DETAILS',
           requestId: 1,
+          taskId: 1,
           sync: false
-        }
-      },
-      response: {items:{Requests:{id:0}}},
-      m: '"Filtered By Request (TASKS_LIST)"'
-    },
-    {
-      levelInfo: Em.Object.create({
-        name: 'HOSTS_LIST',
-        requestId: 1,
-        taskId: 1,
-        sync: false
-      }),
-      e: {
-        name: 'background_operations.get_by_request',
-        successCallback: 'callBackFilteredByRequest',
-        data: {
+        }),
+        e: {
+          name: 'background_operations.get_by_task',
+          successCallback: 'callBackFilteredByTask',
+          data: {
+            taskId: 1,
+            requestId: 1,
+            sync: false
+          }
+        },
+        response: {items: {Tasks: {request_id: 0}}},
+        m: '"Filtered By task"'
+      },
+      {
+        levelInfo: Em.Object.create({
+          name: 'TASKS_LIST',
           requestId: 1,
+          taskId: 1,
           sync: false
-        }
+        }),
+        e: {
+          name: 'background_operations.get_by_request',
+          successCallback: 'callBackFilteredByRequest',
+          data: {
+            requestId: 1,
+            sync: false
+          }
+        },
+        response: {items: {Requests: {id: 0}}},
+        m: '"Filtered By Request (TASKS_LIST)"'
       },
-      response: {items:{Requests:{id:0}}},
-      m: '"Filtered By Request (HOSTS_LIST)"'
-    }
-  ]);
+      {
+        levelInfo: Em.Object.create({
+          name: 'HOSTS_LIST',
+          requestId: 1,
+          taskId: 1,
+          sync: false
+        }),
+        e: {
+          name: 'background_operations.get_by_request',
+          successCallback: 'callBackFilteredByRequest',
+          data: {
+            requestId: 1,
+            sync: false
+          }
+        },
+        response: {items: {Requests: {id: 0}}},
+        m: '"Filtered By Request (HOSTS_LIST)"'
+      }
+    ]);
 
-  describe('#getQueryParams', function() {
-    beforeEach(function() {
-      controller = App.BackgroundOperationsController.create();
+    beforeEach(function () {
       App.testMode = false;
     });
-    afterEach(function() {
+    afterEach(function () {
       App.testMode = true;
     });
 
-    tests.forEach(function(test) {
-      it(test.m, function() {
+    tests.forEach(function (test) {
+      it(test.m, function () {
         controller.set('levelInfo', test.levelInfo);
         var r = controller.getQueryParams();
         expect(r.name).to.equal(test.e.name);
@@ -133,4 +132,534 @@ describe('App.BackgroundOperationsController', function () {
     });
   });
 
+  describe('#startPolling()', function () {
+
+    beforeEach(function () {
+      sinon.spy(App.updater, 'run');
+      sinon.spy(controller, 'requestMostRecent');
+    });
+    afterEach(function () {
+      App.updater.run.restore();
+      controller.requestMostRecent.restore();
+    });
+
+    it('isWorking = false', function () {
+      controller.set('isWorking', false);
+      expect(App.updater.run.calledOnce).to.equal(false);
+      expect(controller.requestMostRecent.calledOnce).to.equal(false);
+    });
+    it('isWorking = true', function () {
+      controller.set('isWorking', true);
+      expect(App.updater.run.calledOnce).to.equal(true);
+      expect(controller.requestMostRecent.calledOnce).to.equal(true);
+    });
+  });
+
+  describe('#callBackForMostRecent()', function () {
+    it('No requests exists', function () {
+      var data = {
+        items: []
+      };
+      controller.callBackForMostRecent(data);
+      expect(controller.get("allOperationsCount")).to.equal(0);
+      expect(controller.get("services")).to.be.empty;
+    });
+    it('One non-running request', function () {
+      var data = {
+        items: [
+          {
+            Requests: {
+              id: 1,
+              request_context: '',
+              task_count: 0,
+              aborted_task_count: 0,
+              completed_task_count: 0,
+              failed_task_count: 0,
+              timed_out_task_count: 0,
+              queued_task_count: 0
+            }
+          }
+        ]
+      };
+      controller.callBackForMostRecent(data);
+      expect(controller.get("allOperationsCount")).to.equal(0);
+      expect(controller.get("services").mapProperty('id')).to.eql([1]);
+    });
+
+
+    it('One running request', function () {
+      var data = {
+        items: [
+          {
+            Requests: {
+              id: 1,
+              request_context: '',
+              task_count: 1,
+              aborted_task_count: 0,
+              completed_task_count: 0,
+              failed_task_count: 0,
+              timed_out_task_count: 0,
+              queued_task_count: 0
+            }
+          }
+        ]
+      };
+      controller.callBackForMostRecent(data);
+      expect(controller.get("allOperationsCount")).to.equal(1);
+      expect(controller.get("services").mapProperty('id')).to.eql([1]);
+    });
+    it('Two requests in order', function () {
+      var data = {
+        items: [
+          {
+            Requests: {
+              id: 1,
+              request_context: ''
+            }
+          },
+          {
+            Requests: {
+              id: 2,
+              request_context: ''
+            }
+          }
+        ]
+      };
+      controller.callBackForMostRecent(data);
+      expect(controller.get("allOperationsCount")).to.equal(0);
+      expect(controller.get("services").mapProperty('id')).to.eql([2, 1]);
+    });
+  });
+
+  describe('#removeOldRequests()', function () {
+    var testCases = [
+      {
+        title: 'No requests exist',
+        content: {
+          currentRequestIds: [],
+          services: []
+        },
+        result: []
+      },
+      {
+        title: 'One current request',
+        content: {
+          currentRequestIds: [1],
+          services: [
+            {id: 1}
+          ]
+        },
+        result: [
+          {id: 1}
+        ]
+      },
+      {
+        title: 'One old request',
+        content: {
+          currentRequestIds: [2],
+          services: [
+            {id: 1}
+          ]
+        },
+        result: []
+      },
+      {
+        title: 'One old request and one is current',
+        content: {
+          currentRequestIds: [2],
+          services: [
+            {id: 1},
+            {id: 2}
+          ]
+        },
+        result: [
+          {id: 2}
+        ]
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.set('services', test.content.services);
+        controller.removeOldRequests(test.content.currentRequestIds);
+        expect(controller.get('services')).to.eql(test.result);
+      });
+    });
+  });
+
+  describe('#isRequestRunning()', function () {
+    var testCases = [
+      {
+        title: 'Counters are missing',
+        request: {
+          Requests: {}
+        },
+        result: false
+      },
+      {
+        title: 'Request has zero tasks',
+        request: {
+          Requests: {
+            task_count: 0,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 0,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      },
+      {
+        title: 'One task in running status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 0,
+            queued_task_count: 0
+          }
+        },
+        result: true
+      },
+      {
+        title: 'One task in queued status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 0,
+            queued_task_count: 1
+          }
+        },
+        result: true
+      },
+      {
+        title: 'One task in aborted status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 1,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 0,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      },
+      {
+        title: 'One task in completed status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 0,
+            completed_task_count: 1,
+            failed_task_count: 0,
+            timed_out_task_count: 0,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      },
+      {
+        title: 'One task in failed status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 1,
+            timed_out_task_count: 0,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      },
+      {
+        title: 'One task in timed out status',
+        request: {
+          Requests: {
+            task_count: 1,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 1,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      },
+      {
+        title: 'One task in timed out status and the second one in running',
+        request: {
+          Requests: {
+            task_count: 2,
+            aborted_task_count: 0,
+            completed_task_count: 0,
+            failed_task_count: 0,
+            timed_out_task_count: 1,
+            queued_task_count: 0
+          }
+        },
+        result: true
+      },
+      {
+        title: 'One task in each status',
+        request: {
+          Requests: {
+            task_count: 5,
+            aborted_task_count: 1,
+            completed_task_count: 1,
+            failed_task_count: 1,
+            timed_out_task_count: 1,
+            queued_task_count: 1
+          }
+        },
+        result: true
+      },
+      {
+        title: 'One task in each status except queued',
+        request: {
+          Requests: {
+            task_count: 5,
+            aborted_task_count: 1,
+            completed_task_count: 1,
+            failed_task_count: 1,
+            timed_out_task_count: 1,
+            queued_task_count: 0
+          }
+        },
+        result: true
+      },
+      {
+        title: 'No tasks in running status',
+        request: {
+          Requests: {
+            task_count: 4,
+            aborted_task_count: 1,
+            completed_task_count: 1,
+            failed_task_count: 1,
+            timed_out_task_count: 1,
+            queued_task_count: 0
+          }
+        },
+        result: false
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        expect(controller.isRequestRunning(test.request)).to.eql(test.result);
+      });
+    });
+  });
+
+  describe('#isOneHost()', function () {
+    var testCases = [
+      {
+        title: 'inputs is null',
+        inputs: null,
+        result: false
+      },
+      {
+        title: 'inputs is "null"',
+        inputs: 'null',
+        result: false
+      },
+      {
+        title: 'inputs is empty object',
+        inputs: '{}',
+        result: false
+      },
+      {
+        title: 'included_hosts is empty',
+        inputs: '{"included_hosts": ""}',
+        result: false
+      },
+      {
+        title: 'included_hosts contain one host',
+        inputs: '{"included_hosts": "host1"}',
+        result: true
+      },
+      {
+        title: 'included_hosts contain two hosts',
+        inputs: '{"included_hosts": "host1,host2"}',
+        result: false
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        expect(controller.isOneHost(test.inputs)).to.eql(test.result);
+      });
+    });
+  });
+
+  describe('#assignScheduleId()', function () {
+    var testCases = [
+      {
+        title: 'isOneHost is false',
+        content: {
+          request: {
+            Requests: {
+              request_schedule: {
+                schedule_id: 1
+              },
+              inputs: null
+            }
+          },
+          requestParams: ''
+        },
+        result: 1
+      },
+      {
+        title: 'isOneHost is true and requestContext is empty',
+        content: {
+          request: {
+            Requests: {
+              request_schedule: {
+                schedule_id: 1
+              },
+              inputs: '{"included_hosts": "host1"}'
+            }
+          },
+          requestParams: {
+            requestContext: ''
+          }
+        },
+        result: 1
+      },
+      {
+        title: 'isOneHost is true and requestContext contains "Recommission"',
+        content: {
+          request: {
+            Requests: {
+              request_schedule: {
+                schedule_id: 1
+              },
+              inputs: '{"included_hosts": "host1"}'
+            }
+          },
+          requestParams: {
+            requestContext: 'Recommission'
+          }
+        },
+        result: null
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.assignScheduleId(test.content.request, test.content.requestParams);
+        expect(test.content.request.Requests.request_schedule.schedule_id).to.equal(test.result);
+      });
+    });
+  });
+
+  describe('#callBackFilteredByRequest()', function () {
+
+    it('request haven\'t tasks and isRunning false', function () {
+      var data = {
+        Requests: {id: 1},
+        tasks: []
+      };
+      var request = Em.Object.create({
+        id: 1,
+        previousTaskStatusMap: {},
+        isRunning: false,
+        progress: 0,
+        status:''
+      });
+      controller.set('services', [request]);
+      controller.callBackFilteredByRequest(data);
+      expect(request.get('previousTaskStatusMap')).to.eql({});
+      expect(request.get('hostsMap')).to.eql({});
+      expect(request.get('isRunning')).to.equal(false);
+    });
+
+    it('request haven\'t tasks and isRunning true', function () {
+      var data = {
+        Requests: {id: 1},
+        tasks: []
+      };
+      var request = Em.Object.create({
+        id: 1,
+        previousTaskStatusMap: {},
+        isRunning: true,
+        progress: 0,
+        status:''
+      });
+      controller.set('services', [request]);
+      controller.callBackFilteredByRequest(data);
+      expect(request.get('previousTaskStatusMap')).to.eql({});
+      expect(request.get('hostsMap')).to.eql({});
+      expect(request.get('isRunning')).to.equal(true);
+    });
+
+    it('request has one completed task', function () {
+      var data = {
+        Requests: {id: 1},
+        tasks: [
+          {
+            Tasks: {
+              id: 1,
+              host_name: 'host1',
+              status: 'COMPLETED'
+            }
+          }
+        ]
+      };
+      var request = Em.Object.create({
+        id: 1,
+        previousTaskStatusMap: {},
+        isRunning: true,
+        progress: 100,
+        status:''
+      });
+      controller.set('services', [request]);
+      controller.callBackFilteredByRequest(data);
+      expect(request.get('previousTaskStatusMap')).to.eql({"1": "COMPLETED"});
+      expect(request.get('hostsMap')['host1'].logTasks.length).to.equal(1);
+      expect(request.get('isRunning')).to.equal(false);
+    });
+
+    it('request has one completed task and one running task', function () {
+      var data = {
+        Requests: {id: 1},
+        tasks: [
+          {
+            Tasks: {
+              id: 1,
+              host_name: 'host1',
+              status: 'COMPLETED'
+            }
+          },
+          {
+            Tasks: {
+              id: 2,
+              host_name: 'host1',
+              status: 'IN_PROGRESS'
+            }
+          }
+        ]
+      };
+      var request = Em.Object.create({
+        id: 1,
+        previousTaskStatusMap: {},
+        isRunning: true,
+        progress: 100,
+        status:''
+      });
+      controller.set('services', [request]);
+      controller.callBackFilteredByRequest(data);
+      expect(request.get('previousTaskStatusMap')).to.eql({"1": "COMPLETED", "2": "IN_PROGRESS"});
+      expect(request.get('hostsMap')['host1'].logTasks.length).to.equal(2);
+      expect(request.get('isRunning')).to.equal(true);
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/ambari-web/test/controllers/global/cluster_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/global/cluster_controller_test.js b/ambari-web/test/controllers/global/cluster_controller_test.js
index 43f0409..9b099f9 100644
--- a/ambari-web/test/controllers/global/cluster_controller_test.js
+++ b/ambari-web/test/controllers/global/cluster_controller_test.js
@@ -22,81 +22,431 @@ require('controllers/global/cluster_controller');
 require('models/host_component');
 require('utils/http_client');
 require('models/service');
+require('models/host');
+require('utils/ajax');
 
 describe('App.clusterController', function () {
   var controller = App.ClusterController.create();
-  App.Service.FIXTURES = [{service_name: 'NAGIOS'}];
+  App.Service.FIXTURES = [
+    {service_name: 'NAGIOS'}
+  ];
 
   describe('#updateLoadStatus()', function () {
 
     controller.set('dataLoadList', Em.Object.create({
-      'item1':false,
-      'item2':false
+      'item1': false,
+      'item2': false
     }));
 
-    it('when none item is loaded then width should be "width:0"', function(){
+    it('when none item is loaded then width should be "width:0"', function () {
       expect(controller.get('clusterDataLoadedPercent')).to.equal('width:0');
     });
-    it('when first item is loaded then isLoaded should be false', function(){
+    it('when first item is loaded then isLoaded should be false', function () {
       controller.updateLoadStatus.call(controller, 'item1');
       expect(controller.get('isLoaded')).to.equal(false);
     });
-    it('when first item is loaded then width should be "width:50%"', function(){
+    it('when first item is loaded then width should be "width:50%"', function () {
       controller.updateLoadStatus.call(controller, 'item1');
       expect(controller.get('clusterDataLoadedPercent')).to.equal('width:50%');
     });
 
-    it('when all items are loaded then isLoaded should be true', function(){
+    it('when all items are loaded then isLoaded should be true', function () {
       controller.updateLoadStatus.call(controller, 'item2');
       expect(controller.get('isLoaded')).to.equal(true);
     });
-    it('when all items are loaded then width should be "width:100%"', function(){
+    it('when all items are loaded then width should be "width:100%"', function () {
       controller.updateLoadStatus.call(controller, 'item2');
       expect(controller.get('clusterDataLoadedPercent')).to.equal('width:100%');
     });
   });
 
-  describe('#loadClusterNameSuccessCallback', function() {
+  describe('#loadClusterName()', function () {
+
+    beforeEach(function () {
+      sinon.spy(App.ajax, 'send');
+    });
+    afterEach(function () {
+      App.ajax.send.restore();
+    });
+
+    it('if clusterName is "mycluster" and reload is false then loadClusterName should return false', function () {
+      controller.set('cluster', {Clusters: {cluster_name: 'mycluster'}});
+      expect(controller.loadClusterName(false)).to.equal(false);
+    });
+
+    it('reload is true and clusterName is not empty', function () {
+      controller.loadClusterName(true);
+      expect(App.ajax.send.calledOnce).to.equal(true);
+      expect(App.get('currentStackVersion')).to.equal('HDP-2.0.5');
+    });
+
+    it('reload is false and clusterName is empty', function () {
+      controller.set('cluster', {Clusters: {cluster_name: ''}});
+      controller.loadClusterName(false);
+      expect(App.ajax.send.calledOnce).to.equal(true);
+      expect(App.get('currentStackVersion')).to.equal('HDP-2.0.5');
+    });
+
+
+  });
+
+  describe('#loadClusterNameSuccessCallback', function () {
     var test_data = {
-      "items" : [
+      "items": [
         {
-          "Clusters" : {
-            "cluster_name" : "tdk",
-            "version" : "HDP-1.3.0"
+          "Clusters": {
+            "cluster_name": "tdk",
+            "version": "HDP-1.3.0"
           }
         }
       ]
     };
-    controller.loadClusterNameSuccessCallback(test_data);
-    it('Check cluster', function() {
+    it('Check cluster', function () {
+      controller.loadClusterNameSuccessCallback(test_data);
       expect(controller.get('cluster.Clusters.cluster_name')).to.equal('tdk');
       expect(controller.get('cluster.Clusters.version')).to.equal('HDP-1.3.0');
       expect(App.get('clusterName')).to.equal('tdk');
     });
   });
 
-  describe('#loadClusterNameErrorCallback', function() {
+  describe('#loadClusterNameErrorCallback', function () {
     controller.loadClusterNameErrorCallback();
-    it('', function() {
+    it('', function () {
       expect(controller.get('isLoaded')).to.equal(true);
     });
   });
 
-  describe('#getUrl', function() {
+  describe('#getServerClockSuccessCallback()', function () {
+    var testCases = [
+      {
+        title: 'if server clock is 1 then currentServerTime should be 1000',
+        data: {
+          RootServiceComponents: {
+            server_clock: 1
+          }
+        },
+        result: 1000
+      },
+      {
+        title: 'if server clock is 0 then currentServerTime should be 0',
+        data: {
+          RootServiceComponents: {
+            server_clock: 0
+          }
+        },
+        result: 0
+      },
+      {
+        title: 'if server clock is 111111111111 then currentServerTime should be 111111111111000',
+        data: {
+          RootServiceComponents: {
+            server_clock: 111111111111
+          }
+        },
+        result: 111111111111000
+      },
+      {
+        title: 'if server clock is 1111111111113 then currentServerTime should be 1111111111113',
+        data: {
+          RootServiceComponents: {
+            server_clock: 1111111111113
+          }
+        },
+        result: 1111111111113
+      }
+    ];
+    var currentServerTime = App.get('currentServerTime');
+    var clockDistance = App.get('clockDistance');
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.getServerClockSuccessCallback(test.data);
+        expect(App.get('currentServerTime')).to.equal(test.result);
+        App.set('clockDistance', clockDistance);
+        App.set('currentServerTime', currentServerTime);
+      });
+    });
+  });
+
+  describe('#getUrl', function () {
     controller.set('clusterName', 'tdk');
     var tests = ['test1', 'test2', 'test3'];
-    it('testMode = true', function() {
+    it('testMode = true', function () {
       App.testMode = true;
-      tests.forEach(function(test) {
+      tests.forEach(function (test) {
         expect(controller.getUrl(test, test)).to.equal(test);
       });
     });
-    it('testMode = false', function() {
+    it('testMode = false', function () {
       App.testMode = false;
-      tests.forEach(function(test) {
+      tests.forEach(function (test) {
         expect(controller.getUrl(test, test)).to.equal(App.apiPrefix + '/clusters/' + controller.get('clusterName') + test);
       });
     });
   });
 
+  describe('#gangliaUrl', function () {
+    it('testMode = true', function () {
+      App.testMode = true;
+      expect(controller.get('gangliaUrl')).to.equal('http://gangliaserver/ganglia/?t=yes');
+    });
+    it('Ganglia service is absent', function () {
+      App.testMode = false;
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal(null);
+    });
+    it('Ganglia doesn\'t  have any components', function () {
+      App.store.load(App.Service, {
+        id: 'GANGLIA',
+        service_name: 'GANGLIA'
+      });
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal(null);
+      expect(controller.get('isGangliaInstalled')).to.equal(true);
+    });
+    it('Ganglia Server doesn\'t  have host', function () {
+      App.store.load(App.HostComponent, {
+        id: 'GANGLIA_SERVER_GANGLIA_host',
+        component_name: 'GANGLIA_SERVER',
+        service_id: 'GANGLIA',
+        host_id: 'GANGLIA_host'
+      });
+      App.store.load(App.Service, {
+        id: 'GANGLIA',
+        service_name: 'GANGLIA',
+        host_components: ['GANGLIA_SERVER_GANGLIA_host']
+      });
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal(null);
+    });
+    it('Ganglia Server host is "GANGLIA_host"', function () {
+      App.store.load(App.Host, {
+        id: 'GANGLIA_host',
+        host_name: 'GANGLIA_host',
+        host_components: ['GANGLIA_SERVER_GANGLIA_host'],
+        public_host_name: 'GANGLIA_host'
+      });
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal("http://GANGLIA_host/ganglia");
+    });
+    it('singleNodeInstall = true', function () {
+      App.set('singleNodeInstall', true);
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal("http://:42080/ganglia");
+    });
+    it('singleNodeAlias is "alias"', function () {
+      App.set('singleNodeAlias', 'alias');
+      controller.set('gangliaWebProtocol', '');
+      expect(controller.get('gangliaUrl')).to.equal("http://alias:42080/ganglia");
+      App.set('singleNodeInstall', false);
+      App.set('singleNodeAlias', '');
+    });
+  });
+
+  describe('#nagiosUrl', function () {
+    it('testMode = true', function () {
+      App.testMode = true;
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal('http://nagiosserver/nagios');
+    });
+    it('Nagios service is absent', function () {
+      App.testMode = false;
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal(null);
+    });
+    it('Nagios doesn\'t  have any components', function () {
+      App.store.load(App.Service, {
+        id: 'NAGIOS',
+        service_name: 'NAGIOS'
+      });
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal(null);
+      expect(controller.get('isNagiosInstalled')).to.equal(true);
+    });
+    it('NAGIOS Server doesn\'t  have host', function () {
+      App.store.load(App.HostComponent, {
+        id: 'NAGIOS_SERVER_NAGIOS_host',
+        component_name: 'NAGIOS_SERVER',
+        service_id: 'NAGIOS',
+        host_id: 'NAGIOS_host'
+      });
+      App.store.load(App.Service, {
+        id: 'NAGIOS',
+        service_name: 'NAGIOS',
+        host_components: ['NAGIOS_SERVER_NAGIOS_host']
+      });
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal(null);
+    });
+    it('NAGIOS Server host is "NAGIOS_host"', function () {
+      App.store.load(App.Host, {
+        id: 'NAGIOS_host',
+        host_name: 'NAGIOS_host',
+        host_components: ['NAGIOS_SERVER_NAGIOS_host'],
+        public_host_name: 'NAGIOS_host'
+      });
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal("http://NAGIOS_host/nagios");
+    });
+    it('singleNodeInstall = true', function () {
+      App.set('singleNodeInstall', true);
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal("http://:42080/nagios");
+    });
+    it('singleNodeAlias is "alias"', function () {
+      App.set('singleNodeAlias', 'alias');
+      controller.set('nagiosWebProtocol', '');
+      expect(controller.get('nagiosUrl')).to.equal("http://alias:42080/nagios");
+    });
+  });
+
+  describe('#nagiosWebProtocol', function () {
+    var testCases = [
+      {
+        title: 'if ambariProperties is null then nagiosWebProtocol should be "http"',
+        data: null,
+        result: 'http'
+      },
+      {
+        title: 'if ambariProperties is empty object then nagiosWebProtocol should be "http"',
+        data: {},
+        result: 'http'
+      },
+      {
+        title: 'if nagios.https is false then nagiosWebProtocol should be "http"',
+        data: {'nagios.https': false},
+        result: 'http'
+      },
+      {
+        title: 'if nagios.https is true then nagiosWebProtocol should be "http"',
+        data: {'nagios.https': true},
+        result: 'https'
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.set('ambariProperties', test.data);
+        expect(controller.get('nagiosWebProtocol')).to.equal(test.result);
+      });
+    });
+  });
+
+  describe('#gangliaWebProtocol', function () {
+    var testCases = [
+      {
+        title: 'if ambariProperties is null then nagiosWebProtocol should be "http"',
+        data: null,
+        result: 'http'
+      },
+      {
+        title: 'if ambariProperties is empty object then nagiosWebProtocol should be "http"',
+        data: {},
+        result: 'http'
+      },
+      {
+        title: 'if nagios.https is false then nagiosWebProtocol should be "http"',
+        data: {'ganglia.https': false},
+        result: 'http'
+      },
+      {
+        title: 'if nagios.https is true then nagiosWebProtocol should be "http"',
+        data: {'ganglia.https': true},
+        result: 'https'
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.set('ambariProperties', test.data);
+        expect(controller.get('gangliaWebProtocol')).to.equal(test.result);
+      });
+    });
+  });
+
+  describe('#startPolling()', 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.calledOnce).to.equal(false);
+      expect(controller.startPolling()).to.equal(false);
+    });
+
+    it('isWorking = true', function () {
+      controller.set('isWorking', true);
+      expect(App.updater.run.calledOnce).to.equal(true);
+      expect(controller.startPolling()).to.equal(true);
+    });
+  });
+
+  describe('#deferServiceMetricsLoad()', function () {
+    beforeEach(function () {
+      sinon.spy(App.serviceMetricsMapper, 'map');
+    });
+    afterEach(function () {
+      App.serviceMetricsMapper.map.restore();
+    });
+    it('json is null', function () {
+      controller.set('serviceMetricsJson', {});
+      controller.set('dataLoadList.serviceMetrics', false);
+      controller.deferServiceMetricsLoad(null);
+      expect(controller.get('serviceMetricsJson')).to.equal(null);
+      expect(controller.get('dataLoadList.serviceMetrics')).to.equal(true);
+      expect(App.serviceMetricsMapper.map.calledOnce).to.equal(true);
+    });
+    it('json is correct', function () {
+      controller.deferServiceMetricsLoad({data: ''});
+      expect(controller.get('serviceMetricsJson')).to.eql({data: ''});
+    });
+    it('json is correct and dataLoadList.hosts is true', function () {
+      controller.set('serviceMetricsJson', {});
+      controller.set('dataLoadList.serviceMetrics', false);
+      controller.set('dataLoadList.hosts', true);
+      controller.deferServiceMetricsLoad(null);
+      expect(controller.get('dataLoadList.serviceMetrics')).to.equal(true);
+      expect(App.serviceMetricsMapper.map.calledOnce).to.equal(true);
+    });
+  });
+
+  describe('#clusterName', function () {
+    var testCases = [
+      {
+        title: 'if cluster is null then clusterName should be null',
+        data: null,
+        result: null
+      },
+      {
+        title: 'if cluster.Clusters.cluster_name is null then clusterName should be null',
+        data: {
+          Clusters: {
+            cluster_name: null
+          }
+        },
+        result: null
+      },
+      {
+        title: 'if cluster.Clusters.cluster_name is null then clusterName should be null',
+        data: {
+          Clusters: {
+            cluster_name: 'mycluster'
+          }
+        },
+        result: 'mycluster'
+      }
+    ];
+
+    testCases.forEach(function (test) {
+      it(test.title, function () {
+        controller.set('cluster', test.data);
+        expect(controller.get('clusterName')).to.equal(test.result);
+      });
+    });
+  });
+
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/cc92b610/ambari-web/test/controllers/main/admin/cluster_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/admin/cluster_test.js b/ambari-web/test/controllers/main/admin/cluster_test.js
index ce35948..b23f728 100644
--- a/ambari-web/test/controllers/main/admin/cluster_test.js
+++ b/ambari-web/test/controllers/main/admin/cluster_test.js
@@ -23,49 +23,49 @@ require('controllers/main/admin/cluster');
 
 describe('App.MainAdminClusterController', function () {
 
-  App.set('currentStackVersion', 'HDP-1.2.2');
-  App.set('defaultStackVersion', 'HDP-1.2.2');
   var data = {
-    "items" : [
+    "items": [
       {
-        "Versions" : {
-          "stack_version" : "1.3.1",
-          "min_upgrade_version" : "1.2.0"
+        "Versions": {
+          "stack_version": "1.3.1",
+          "min_upgrade_version": "1.2.0"
         }
-      },               
+      },
       {
-        "Versions" : {
-          "stack_version" : "1.3.0",
-          "min_upgrade_version" : "1.2.0"
+        "Versions": {
+          "stack_version": "1.3.0",
+          "min_upgrade_version": "1.2.0"
         }
       },
       {
-        "Versions" : {
-          "stack_version" : "1.2.2",
-          "min_upgrade_version" : "1.2.0"
+        "Versions": {
+          "stack_version": "1.2.2",
+          "min_upgrade_version": "1.2.0"
         }
       },
       {
-        "Versions" : {
-          "stack_version" : "1.2.0",
-          "min_upgrade_version" : "1.2.0"
+        "Versions": {
+          "stack_version": "1.2.0",
+          "min_upgrade_version": "1.2.0"
         }
       }
     ]
   };
 
   describe('#updateUpgradeVersionSuccessCallback()', function () {
-    it('upgrade version of stack should be "HDP-1.3.0"', function(){
+    it('upgrade version of stack should be "HDP-1.3.1"', function () {
+      App.set('currentStackVersion', 'HDP-1.2.2');
       var controller = App.MainAdminClusterController.create({
-        parseServicesInfo:function(){}
+        parseServicesInfo: function () {}
       });
       controller.updateUpgradeVersionSuccessCallback.call(controller, data);
       expect(controller.get('upgradeVersion')).to.equal('HDP-1.3.1');
     });
-    it('if min upgrade version less then current then upgrade version equal current', function(){
+    it('if min upgrade version less then current then upgrade version equal current', function () {
+      App.set('currentStackVersion', 'HDP-1.2.2');
       data.items[0].Versions.min_upgrade_version = "1.2.3";
       var controller = App.MainAdminClusterController.create({
-        parseServicesInfo:function(){}
+        parseServicesInfo: function () {}
       });
       controller.updateUpgradeVersionSuccessCallback.call(controller, data);
       expect(controller.get('upgradeVersion')).to.equal('HDP-1.2.2');