You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/03/18 11:05:03 UTC
tez git commit: TEZ-3170. Tez UI 2: Swimlane - Display computed
events, event bars & dependencies (sree)
Repository: tez
Updated Branches:
refs/heads/master 44c660a34 -> c9c7d8099
TEZ-3170. Tez UI 2: Swimlane - Display computed events, event bars & dependencies (sree)
Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/c9c7d809
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/c9c7d809
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/c9c7d809
Branch: refs/heads/master
Commit: c9c7d80997373f424abba9a0ec6a99b8db983d2b
Parents: 44c660a
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Fri Mar 18 15:34:33 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Fri Mar 18 15:34:33 2016 +0530
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../components/em-swimlane-blocking-event.js | 50 +++++++
.../app/components/em-swimlane-event-bar.js | 67 +++++++++
.../webapp/app/components/em-swimlane-event.js | 23 ++-
.../components/em-swimlane-process-visual.js | 11 +-
.../main/webapp/app/components/em-swimlane.js | 79 ++++++++++
.../main/webapp/app/controllers/dag/swimlane.js | 35 +++++
.../src/main/webapp/app/styles/em-swimlane.less | 58 +++++---
.../components/em-swimlane-blocking-event.hbs | 19 +++
.../components/em-swimlane-event-bar.hbs | 19 +++
.../templates/components/em-swimlane-event.hbs | 4 +-
.../components/em-swimlane-process-visual.hbs | 21 ++-
.../app/templates/components/em-swimlane.hbs | 5 +-
.../webapp/app/templates/dag/index/index.hbs | 1 +
.../main/webapp/app/templates/dag/swimlane.hbs | 3 +-
tez-ui2/src/main/webapp/app/utils/process.js | 101 +++++++++++++
.../src/main/webapp/app/utils/vertex-process.js | 109 ++++++++++++++
.../em-swimlane-blocking-event-test.js | 78 ++++++++++
.../components/em-swimlane-event-bar-test.js | 43 ++++++
.../components/em-swimlane-event-test.js | 13 +-
.../em-swimlane-process-visual-test.js | 15 +-
.../integration/components/em-swimlane-test.js | 42 +++++-
.../tests/unit/controllers/dag/swimlane-test.js | 45 ++++++
.../webapp/tests/unit/utils/process-test.js | 147 +++++++++++++++++++
.../tests/unit/utils/vertex-process-test.js | 98 +++++++++++++
25 files changed, 1034 insertions(+), 53 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index f14a2fa..30e4fc6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1885,6 +1885,7 @@ ALL CHANGES
TEZ-642. Fix poms for release. (hitesh)
TEZ-643. Change getProgress APIs to return some form of progress and 1.0f once the map or reduce phase complete. (sseth)
TEZ-3160. Tez UI 2: Swimlane - Create swimlane page & component (sree)
+ TEZ-3170. Tez UI 2: Swimlane - Display computed events, event bars & dependencies (sree)
Release 0.2.0-incubating: 2013-11-30
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js
new file mode 100644
index 0000000..a58ded8
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-blocking-event.js
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+
+ process: null,
+ blocking: null,
+ events: null,
+
+ classNames: ["em-swimlane-blocking-event"],
+
+ blockingEvent: Ember.computed("events.length", "process.blockingEventName", function () {
+ var events = this.get("events"),
+ blockingEventName = this.get("process.blockingEventName");
+
+ return events.find(function (event) {
+ return event.name === blockingEventName;
+ });
+ }),
+
+ didInsertElement: Ember.observer("blockingEvent", function () {
+ var blockerEventHeight = (this.get("blocking.index") - this.get("process.index")) * 30;
+
+ this.$().css({
+ "left": this.get("blockingEvent.pos") + "%"
+ });
+ this.$(".event-line").css({
+ "height": `${blockerEventHeight}px`,
+ "border-color": this.get("process").getColor()
+ });
+ }),
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js
new file mode 100644
index 0000000..e0e835e
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-event-bar.js
@@ -0,0 +1,67 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+
+ process: null,
+ events: [],
+
+ bars: [],
+ bar: null,
+ barIndex: 0,
+
+ classNames: ["em-swimlane-event-bar"],
+
+ fromEvent: Ember.computed("events.length", "bar.fromEvent", function () {
+ var events = this.get("events"),
+ fromEventName = this.get("bar.fromEvent");
+ return events.find(function (event) {
+ return event.name === fromEventName;
+ });
+ }),
+ toEvent: Ember.computed("events.length", "bar.toEvent", function () {
+ var events = this.get("events"),
+ toEventName = this.get("bar.toEvent");
+ return events.find(function (event) {
+ return event.name === toEventName;
+ });
+ }),
+
+ didInsertElement: Ember.observer("fromEvent.pos", "toEvent.pos", "barIndex", function () {
+ var fromEventPos = this.get("fromEvent.pos"),
+ toEventPos = this.get("toEvent.pos"),
+ color = this.get("bar.color") ||
+ this.get("process").getColor(1 - (this.get("barIndex") / this.get("bars.length")));
+
+ if(fromEventPos && toEventPos) {
+ this.$().show();
+ this.$(".event-bar").css({
+ left: fromEventPos + "%",
+ right: (100 - toEventPos) + "%",
+ "background-color": color,
+ "border-color": this.get("process").getColor()
+ });
+ }
+ else {
+ this.$().hide();
+ }
+ })
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js
index a292085..5eb6f0a 100644
--- a/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js
+++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-event.js
@@ -20,14 +20,25 @@ import Ember from 'ember';
export default Ember.Component.extend({
- title: null,
- position: 0,
- time: 0,
+ process: null,
+ event: null,
classNames: ["em-swimlane-event"],
- didInsertElement: Ember.observer("position", function () {
- this.$().css("left", this.get("position") + "%");
- })
+ didInsertElement: Ember.observer("event.pos", function () {
+ var color = this.get("process").getColor();
+
+ this.$().css({
+ "left": this.get("event.pos") + "%"
+ });
+ this.$(".event-line").css("border-color", color);
+ this.$(".event-bubble").css("border-color", color);
+ }),
+
+ actions: {
+ showTooltip: function () {
+ console.log(this.get("event.name"));
+ }
+ }
});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js
index b21eadb..5942cf1 100644
--- a/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js
+++ b/tez-ui2/src/main/webapp/app/components/em-swimlane-process-visual.js
@@ -26,17 +26,18 @@ export default Ember.Component.extend({
endTime: 0,
timeWindow: 0,
- events: [],
+ normalizedEvents: [],
startEvent: null,
endEvent: null,
+ eventBars: [],
classNames: ["em-swimlane-process-visual"],
didInsertElement: function () {
Ember.run.later(this, "normalizeEvents");
},
- normalizeEvents: Ember.observer("process.events.@each.timestamp", "startTime", "timeWindow", function () {
+ normalizeEvents: Ember.observer("process.events.@each.time", "startTime", "timeWindow", function () {
var events = Ember.get(this.get("process"), "events") || [],
startEvent,
endEvent,
@@ -45,8 +46,7 @@ export default Ember.Component.extend({
timeWindow = this.get("timeWindow");
events = events.map(function (event) {
- var position = ((event.timestamp - startTime) / timeWindow) * 100;
-
+ var position = ((event.time - startTime) / timeWindow) * 100;
event = {
name: event.name,
text: event.text || event.name,
@@ -65,7 +65,7 @@ export default Ember.Component.extend({
});
this.setProperties({
- events: events,
+ normalizedEvents: events,
startEvent: startEvent,
endEvent: endEvent
});
@@ -75,6 +75,7 @@ export default Ember.Component.extend({
this.$(".event-window-line").css({
left: this.get("startEvent.pos") + "%",
right: (100 - this.get("endEvent.pos")) + "%",
+ "background-color": this.get("process").getColor()
});
})
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/components/em-swimlane.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/em-swimlane.js b/tez-ui2/src/main/webapp/app/components/em-swimlane.js
index 93a2cff..3f22c50 100644
--- a/tez-ui2/src/main/webapp/app/components/em-swimlane.js
+++ b/tez-ui2/src/main/webapp/app/components/em-swimlane.js
@@ -19,6 +19,18 @@
import Ember from 'ember';
import ProcessDefinition from '../utils/process-definition';
+import Process from '../utils/process';
+
+function getVibrantHSL(colorNum, totalColors) {
+ if (totalColors < 1){
+ totalColors = 1;
+ }
+ return {
+ h: colorNum * (360 / totalColors) % 360,
+ s: 100 - (colorNum % 2) * 30,
+ l: 40
+ };
+}
export default Ember.Component.extend({
@@ -30,8 +42,75 @@ export default Ember.Component.extend({
startTime: null,
endTime: null,
+ eventBars: [],
+
timeWindow: Ember.computed("startTime", "endTime", function () {
return Math.max(0, this.get("endTime") - this.get("startTime"));
+ }),
+
+ normalizedProcesses: Ember.computed("processes.@each.blockers", function () {
+ var processes = this.get("processes"),
+ processCount = processes.length,
+ normalizedProcesses,
+ idHash = {},
+ containsBlockers = false;
+
+ // Validate and reset blocking
+ processes.forEach(function (process) {
+ if(!(process instanceof Process)) {
+ Ember.Logger.error("em-swimlane : Unknown type, must be of type Process");
+ }
+
+ if(process.get("blockers.length")) {
+ containsBlockers = true;
+ }
+ process.set("blocking", Ember.A());
+ });
+
+ if(containsBlockers) {
+ normalizedProcesses = [];
+
+ // Recreate blocking list
+ processes.forEach(function (process) {
+ var blockers = process.get("blockers");
+ if(blockers) {
+ blockers.forEach(function (blocker) {
+ blocker.get("blocking").push(process);
+ });
+ }
+ });
+
+ // Give an array of the processes in blocking order
+ processes.forEach(function (process) {
+ if(process.get("blocking.length") === 0) { // The root processes
+ normalizedProcesses.push(process);
+ normalizedProcesses.push.apply(normalizedProcesses, process.getAllBlockers());
+ }
+ });
+ normalizedProcesses.reverse();
+ normalizedProcesses = normalizedProcesses.filter(function (process, index) {
+ // Filters out the recurring processes in the list (after graph traversal), we just
+ // need the top processes
+ var id = process.get("_id");
+ if(idHash[id] === undefined) {
+ idHash[id] = index;
+ }
+ return idHash[id] === index;
+ });
+ }
+ else {
+ normalizedProcesses = processes;
+ }
+
+ // Set process colors & index
+ normalizedProcesses.forEach(function (process, index) {
+ process.setProperties({
+ color: getVibrantHSL(index, processCount),
+ index: index
+ });
+ });
+
+ return Ember.A(normalizedProcesses);
})
});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js b/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js
index 1028a2c..1699708 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag/swimlane.js
@@ -20,6 +20,7 @@ import Ember from 'ember';
import MultiTableController from '../multi-table';
import ColumnDefinition from 'em-table/utils/column-definition';
+import VertexProcess from '../../utils/vertex-process';
import fullscreen from 'em-tgraph/utils/fullscreen';
@@ -40,4 +41,38 @@ export default MultiTableController.extend({
}
},
+ processes: Ember.computed("model", function () {
+ var processes = [],
+ processHash = {},
+
+ dagPlanEdges = this.get("model.firstObject.dag.edges");
+
+ // Create process instances for each vertices
+ this.get("model").forEach(function (vertex) {
+ var process = VertexProcess.create({
+ vertex: vertex,
+ blockers: Ember.A()
+ });
+ processHash[vertex.get("name")] = process;
+ processes.push(process);
+ });
+
+ // Add process(vertex) dependencies based on dagPlan
+ dagPlanEdges.forEach(function (edge) {
+ var process = processHash[edge.outputVertexName];
+ if(process) {
+ process.blockers.push(processHash[edge.inputVertexName]);
+ }
+ });
+
+ return Ember.A(processes);
+ }),
+
+ eventBars: [{
+ fromEvent: "VERTEX_TASK_START",
+ toEvent: "VERTEX_TASK_FINISH",
+ }, {
+ fromEvent: "BLOCKING_VERTICES_COMPLETE",
+ toEvent: "VERTEX_TASK_FINISH",
+ }]
});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/styles/em-swimlane.less
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/styles/em-swimlane.less b/tez-ui2/src/main/webapp/app/styles/em-swimlane.less
index 5087e8f..a982712 100644
--- a/tez-ui2/src/main/webapp/app/styles/em-swimlane.less
+++ b/tez-ui2/src/main/webapp/app/styles/em-swimlane.less
@@ -25,14 +25,13 @@
.process-names {
width: 100px;
+ border-right: 1px solid @border-color;
}
.process-visuals {
position: absolute;
left: 100px;
right: 0px;
top: 0px;
-
- border-left: 1px solid @border-color;
}
}
@@ -52,20 +51,32 @@
position: relative;
height: 30px;
+ margin-left: 10px;
+
cursor: pointer;
.base-line {
position: relative;
height: 1px;
+ margin-left: -10px;
top: unit(unit(@process-height) * 0.5, get-unit(@process-height));
border-top: 1px dotted @border-color;
}
.event-window-line {
position: absolute;
- top: unit(unit(@process-height) * 0.5, get-unit(@process-height));
- border-top: 1px solid;
- height: 1px;
+ top: unit(unit(@process-height) * 0.5 - 1, get-unit(@process-height));
+ height: 3px;
+ }
+
+ .event-bar {
+ position: absolute;
+ top: unit((unit(@process-height) * 0.5) - 10, get-unit(@process-height));
+ height: 20px;
+ background-color: @border-lite;
+ border-radius: 2px;
+ border: 1px solid;
+ margin-right: -1px;
}
}
@@ -73,10 +84,10 @@
position: absolute;
top: unit(unit(@process-height) * 0.5, get-unit(@process-height));
- .event-bar {
+ .event-line {
position: absolute;
- top: -10px;
- height: 20px;
+ top: -9px;
+ height: 18px;
border-left: 1px solid;
}
@@ -87,23 +98,36 @@
bottom: 0;
left: 0;
- -webkit-transition: top .2s, right .2s, bottom .2s, left .2s; /* Safari */
- transition: top .2s, right .2s, bottom .2s, left .2s;
- transition-timing-function: cubic-bezier(.87,-.41,.19,1.44);
+ -webkit-transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s; /* Safari */
+ transition: top .2s, right .2s, bottom .2s, left .2s, border-width .2s;
+ transition-timing-function: cubic-bezier(1.44);
- border-radius: 5px;
+ border-radius: 7px;
+ border: 0px solid;
+ background-color: white;
+ }
+}
+
+.em-swimlane-blocking-event {
+ position: absolute;
+ top: unit(unit(@process-height) * 0.5, get-unit(@process-height));
- background-color: black;
+ .event-line {
+ position: absolute;
+ top: 0px;
+ border-left: 1px solid;
}
}
.em-swimlane-process-visual {
&:hover {
.event-bubble {
- top: -5px;
- right: -6px;
- bottom: -6px;
- left: -5px;
+ top: -7px;
+ right: -8px;
+ bottom: -8px;
+ left: -7px;
+
+ border: 2px solid;
}
}
}
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-blocking-event.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-blocking-event.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-blocking-event.hbs
new file mode 100644
index 0000000..0fabd16
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-blocking-event.hbs
@@ -0,0 +1,19 @@
+{{!
+ * 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.
+}}
+
+<div class="event-line"></div>
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event-bar.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event-bar.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event-bar.hbs
new file mode 100644
index 0000000..b2cc9bd
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event-bar.hbs
@@ -0,0 +1,19 @@
+{{!
+ * 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.
+}}
+
+<div class="event-bar"></div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs
index 0211466..9b6330f 100644
--- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-event.hbs
@@ -16,5 +16,5 @@
* limitations under the License.
}}
-<div class="event-bar"></div>
-<div class="event-bubble"></div>
\ No newline at end of file
+<div class="event-line"></div>
+<div class="event-bubble" {{action "showTooltip" on="mouseEnter"}}></div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs
index 6a3a7b9..6e4603d 100644
--- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane-process-visual.hbs
@@ -17,11 +17,18 @@
}}
<div class="base-line"></div>
-{{#each events as |event|}}
- {{em-swimlane-event
- title=event.text
- position=event.pos
- time=event.time
- }}
+<div class="event-window-line"></div>
+{{#each process.blocking as |blocking|}}
+ {{em-swimlane-blocking-event process=process blocking=blocking events=normalizedEvents}}
+{{/each}}
+{{#each eventBars as |bar index|}}
+ {{em-swimlane-event-bar
+ events=normalizedEvents
+ bar=bar
+ barIndex=index
+ bars=eventBars
+ process=process}}
+{{/each}}
+{{#each normalizedEvents as |event|}}
+ {{em-swimlane-event process=process event=event}}
{{/each}}
-<div class="event-window-line"></div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs
index a9ab876..a4777f0 100644
--- a/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/components/em-swimlane.hbs
@@ -17,14 +17,15 @@
}}
<div class="process-names">
- {{#each processes as |process|}}
+ {{#each normalizedProcesses as |process|}}
{{em-swimlane-process-name process=process definition=processDefinition}}
{{/each}}
</div><div class="process-visuals">
- {{#each processes as |process|}}
+ {{#each normalizedProcesses as |process|}}
{{em-swimlane-process-visual
process=process
definition=processDefinition
+ eventBars=eventBars
startTime=startTime
endTime=endTime
timeWindow=timeWindow
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/dag/index/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dag/index/index.hbs b/tez-ui2/src/main/webapp/app/templates/dag/index/index.hbs
index 02c88da..c6864fb 100644
--- a/tez-ui2/src/main/webapp/app/templates/dag/index/index.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dag/index/index.hbs
@@ -68,6 +68,7 @@
enableSearch=false
enablePagination=false
+ rowCount=model.length
searchAction="searchChanged"
sortAction="sortChanged"
rowAction="rowCountChanged"
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs b/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs
index adb8586..a2b2cbe 100644
--- a/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dag/swimlane.hbs
@@ -25,7 +25,8 @@
{{em-swimlane
columns=visibleColumns
- processes=model
+ processes=processes
+ eventBars=eventBars
startTime=model.firstObject.dag.startTime
endTime=model.firstObject.dag.endTime
}}
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/utils/process.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/utils/process.js b/tez-ui2/src/main/webapp/app/utils/process.js
new file mode 100644
index 0000000..eba3e72
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/utils/process.js
@@ -0,0 +1,101 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+var processIndex = 1;
+
+export default Ember.Object.extend({
+ _id: null,
+
+ name: null,
+ events: null,
+
+ index: 0,
+ color: null,
+
+ blockers: null, // Array of processes that's blocking the current process
+ blocking: null, // Array of processes blocked by the current process
+
+ init: function () {
+ this.set("_id", `process-id-${processIndex}`);
+ processIndex++;
+ },
+
+ getColor: function (lightnessFactor) {
+ var color = this.get("color"),
+ l;
+
+ if(!color) {
+ return "#0";
+ }
+ l = color.l;
+ if(lightnessFactor !== undefined) {
+ l += 5 + 25 * lightnessFactor;
+ }
+ return `hsl( ${color.h}, ${color.s}%, ${l}% )`;
+ },
+
+ startEvent: Ember.computed("events.@each.time", function () {
+ var events = this.get("events"),
+ startEvent;
+ if(events) {
+ startEvent = events[0];
+ events.forEach(function (event) {
+ if(startEvent.time > event.time) {
+ startEvent = event;
+ }
+ });
+ }
+ return startEvent;
+ }),
+
+ endEvent: Ember.computed("events.@each.time", function () {
+ var events = this.get("events"),
+ endEvent;
+ if(events) {
+ endEvent = events[events.length - 1];
+ events.forEach(function (event) {
+ if(endEvent.time < event.time) {
+ endEvent = event;
+ }
+ });
+ }
+ return endEvent;
+ }),
+
+ getAllBlockers: function (parentHash) {
+ var blockers = [],
+ currentId = this.get("_id");
+
+ parentHash = parentHash || {}; // To keep a check on cyclic blockers
+
+ parentHash[currentId] = true;
+ if(this.get("blockers.length")) {
+ this.get("blockers").forEach(function (blocker) {
+ if(!parentHash[blocker.get("_id")]) {
+ blockers.push(blocker);
+ blockers.push.apply(blockers, blocker.getAllBlockers(parentHash));
+ }
+ });
+ }
+ parentHash[currentId] = false;
+
+ return blockers;
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/app/utils/vertex-process.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/utils/vertex-process.js b/tez-ui2/src/main/webapp/app/utils/vertex-process.js
new file mode 100644
index 0000000..e48532d
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/utils/vertex-process.js
@@ -0,0 +1,109 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+import Process from './process';
+
+const EVENT_TEXTS = {
+ VERTEX_INITIALIZED: "Initialized",
+ VERTEX_STARTED: "Started",
+ VERTEX_FINISHED: "Finished",
+ VERTEX_TASK_START: "First Task Start",
+ VERTEX_TASK_FINISH: "All Tasks Complete",
+ BLOCKING_VERTICES_COMPLETE: "All Blocking Vertices Complete"
+};
+
+export default Process.extend({
+ vertex: null,
+
+ name: Ember.computed.oneWay("vertex.name"),
+ completeTime: Ember.computed.oneWay("vertex.endTime"),
+
+ blockingEventName: "VERTEX_FINISHED",
+
+ events: Ember.computed(
+ "vertex.events.@each.timestamp",
+ "vertex.firstTaskStartTime",
+ "vertex.lastTaskFinishTime",
+ "unblockTime",
+ function () {
+ var events = this.get("vertex.events").map(function (event) {
+ return {
+ name: event.eventtype,
+ test: EVENT_TEXTS[event.eventtype],
+ time: event.timestamp
+ };
+ }),
+ firstTaskStartTime = this.get("vertex.firstTaskStartTime"),
+ lastTaskFinishTime = this.get("vertex.lastTaskFinishTime"),
+ unblockTime = this.get("unblockTime");
+
+ if(firstTaskStartTime) {
+ let type = "VERTEX_TASK_START";
+ events.push({
+ name: type,
+ test: EVENT_TEXTS[type],
+ time: firstTaskStartTime
+ });
+ }
+
+ if(lastTaskFinishTime) {
+ let type = "VERTEX_TASK_FINISH";
+ events.push({
+ name: type,
+ test: EVENT_TEXTS[type],
+ time: lastTaskFinishTime
+ });
+ }
+
+ if(unblockTime && unblockTime >= firstTaskStartTime) {
+ let type = "BLOCKING_VERTICES_COMPLETE";
+ events.push({
+ name: type,
+ test: EVENT_TEXTS[type],
+ time: unblockTime
+ });
+ }
+
+ return events;
+ }
+ ),
+
+ unblockTime: Ember.computed("blockers.@each.completeTime", function () {
+ var blockers = this.get("blockers"),
+ time;
+
+ if(blockers) {
+ time = 0;
+ for(var i = 0, length = blockers.length; i < length; i++) {
+ let blockerComplete = blockers[i].get("completeTime");
+
+ if(!blockerComplete) {
+ time = undefined;
+ break;
+ }
+ else if(blockerComplete > time) {
+ time = blockerComplete;
+ }
+ }
+ }
+
+ return time;
+ }),
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-blocking-event-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-blocking-event-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-blocking-event-test.js
new file mode 100644
index 0000000..3ffab01
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-blocking-event-test.js
@@ -0,0 +1,78 @@
+/**
+ * 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.
+ */
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+import Process from 'tez-ui/utils/process';
+
+moduleForComponent('em-swimlane-blocking-event', 'Integration | Component | em swimlane blocking event', {
+ integration: true
+});
+
+test('Basic creation test', function(assert) {
+ this.set("process", Process.create());
+ this.set("events", []);
+
+ this.render(hbs`{{em-swimlane-blocking-event process=process events=events}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:" + EOL +
+ this.render(hbs`
+ {{#em-swimlane-blocking-event process=process events=events}}
+ template block text
+ {{/em-swimlane-blocking-event}}
+ `);
+
+ assert.equal(this.$().text().trim(), '');
+});
+
+test('Blocking test', function(assert) {
+ var blockingEventName = "blockingEvent",
+ processIndex = 5,
+ blockingIndex = 7,
+ processColor = "#123456";
+
+ this.set("process", Process.create({
+ blockingEventName: blockingEventName,
+ index: processIndex,
+ getColor: function () {
+ return processColor;
+ },
+ events: []
+ }));
+ this.set("normalizedEvents", [{
+ name: "e1",
+ pos: 10
+ }, {
+ name: blockingEventName,
+ pos: 20
+ }, {
+ name: "e2",
+ pos: 30
+ }]);
+ this.set("blocking", Process.create({
+ index: blockingIndex
+ }));
+
+ this.render(hbs`{{em-swimlane-blocking-event process=process events=normalizedEvents blocking=blocking}}`);
+
+ assert.equal(this.$(".em-swimlane-blocking-event").attr("style").trim(), 'left: 20%;');
+ assert.equal(this.$(".event-line").css("height"), ((blockingIndex - processIndex) * 30) + "px");
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-bar-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-bar-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-bar-test.js
new file mode 100644
index 0000000..d05924f
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-bar-test.js
@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+import Process from 'tez-ui/utils/process';
+
+moduleForComponent('em-swimlane-event-bar', 'Integration | Component | em swimlane event bar', {
+ integration: true
+});
+
+test('Basic creation test', function(assert) {
+ this.set("process", Process.create());
+
+ this.render(hbs`{{em-swimlane-event-bar process=process}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:" + EOL +
+ this.render(hbs`
+ {{#em-swimlane-event-bar process=process}}
+ template block text
+ {{/em-swimlane-event-bar}}
+ `);
+
+ assert.equal(this.$().text().trim(), '');
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-test.js
index 9e9764e..034d288 100644
--- a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-test.js
+++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-event-test.js
@@ -19,6 +19,8 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
+import Process from 'tez-ui/utils/process';
+
import wait from 'ember-test-helpers/wait';
moduleForComponent('em-swimlane-event', 'Integration | Component | em swimlane event', {
@@ -26,15 +28,16 @@ moduleForComponent('em-swimlane-event', 'Integration | Component | em swimlane e
});
test('Basic creation test', function(assert) {
+ this.set("process", Process.create({}));
- this.render(hbs`{{em-swimlane-event}}`);
+ this.render(hbs`{{em-swimlane-event process=process}}`);
assert.ok(this.$(".event-bar"));
assert.ok(this.$(".event-window"));
// Template block usage:" + EOL +
this.render(hbs`
- {{#em-swimlane-event}}
+ {{#em-swimlane-event process=process}}
template block text
{{/em-swimlane-event}}
`);
@@ -44,8 +47,12 @@ test('Basic creation test', function(assert) {
});
test('Event position test', function(assert) {
+ this.set("process", Process.create());
+ this.set("event", {
+ pos: 60
+ });
- this.render(hbs`{{em-swimlane-event position=60}}`);
+ this.render(hbs`{{em-swimlane-event process=process event=event}}`);
return wait().then(() => {
assert.equal(this.$(".em-swimlane-event").attr("style").trim(), "left: 60%;", "em-swimlane-event");
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js
index 5a180bb..ffc7b56 100644
--- a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js
+++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-process-visual-test.js
@@ -21,14 +21,14 @@ import hbs from 'htmlbars-inline-precompile';
import wait from 'ember-test-helpers/wait';
+import Process from 'tez-ui/utils/process';
+
moduleForComponent('em-swimlane-process-visual', 'Integration | Component | em swimlane process visual', {
integration: true
});
test('Basic creation test', function(assert) {
- this.set("process", {
- events: []
- });
+ this.set("process", Process.create());
this.render(hbs`{{em-swimlane-process-visual process=process}}`);
@@ -47,19 +47,20 @@ test('Basic creation test', function(assert) {
});
test('Events test', function(assert) {
- this.set("process", {
+ this.set("process", Process.create({
events: [{
- timestamp: 5
+ time: 5
}, {
- timestamp: 7
+ time: 7
}]
- });
+ }));
this.render(hbs`{{em-swimlane-process-visual process=process startTime=0 timeWindow=10}}`);
return wait().then(() => {
var events = this.$(".em-swimlane-event");
+
assert.equal(events.length, 2);
assert.equal(events.eq(0).attr("style").trim(), "left: 50%;", "em-swimlane-event 1 left");
assert.equal(events.eq(1).attr("style").trim(), "left: 70%;", "em-swimlane-event 2 left");
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js
index 1e4c938..59e543d 100644
--- a/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js
+++ b/tez-ui2/src/main/webapp/tests/integration/components/em-swimlane-test.js
@@ -19,6 +19,8 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
+import Process from 'tez-ui/utils/process';
+
moduleForComponent('em-swimlane', 'Integration | Component | em swimlane', {
integration: true
});
@@ -27,11 +29,11 @@ test('Basic creation test', function(assert) {
var testName1 = "TestName1",
testName2 = "TestName2";
- this.set("processes", [{
+ this.set("processes", [Process.create({
name: testName1
- }, {
+ }), Process.create({
name: testName2
- }]);
+ })]);
this.render(hbs`{{em-swimlane processes=processes}}`);
@@ -48,3 +50,37 @@ test('Basic creation test', function(assert) {
assert.equal(this.$().text().trim().indexOf(testName1), 0);
assert.notEqual(this.$().text().trim().indexOf(testName2), -1);
});
+
+test('Normalization (Blocker based sorting) test - On a graph', function(assert) {
+ var p1 = Process.create({
+ name: "P1"
+ }),
+ p2 = Process.create({
+ name: "P2"
+ }),
+ p3 = Process.create({
+ name: "P3",
+ blockers: [p1, p2]
+ }),
+ p4 = Process.create({
+ name: "P4",
+ blockers: [p1]
+ }),
+ p5 = Process.create({
+ name: "P5",
+ blockers: [p3, p4]
+ });
+
+ this.set("processes", [p5, p4, p3, p2, p1]);
+
+ this.render(hbs`{{em-swimlane processes=processes}}`);
+
+ let names = this.$(".em-swimlane-process-name");
+
+ assert.equal(names.length, 5);
+ assert.equal(names.eq(0).text().trim(), p1.name);
+ assert.equal(names.eq(1).text().trim(), p4.name);
+ assert.equal(names.eq(2).text().trim(), p2.name);
+ assert.equal(names.eq(3).text().trim(), p3.name);
+ assert.equal(names.eq(4).text().trim(), p5.name);
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/unit/controllers/dag/swimlane-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/swimlane-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/swimlane-test.js
index 7886251..3013a23 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/swimlane-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/swimlane-test.js
@@ -38,4 +38,49 @@ test('Basic creation test', function(assert) {
assert.ok(controller);
assert.ok(controller.breadcrumbs);
assert.ok(controller.columns);
+ assert.ok(controller.processes);
+ assert.ok(controller.eventBars);
+});
+
+test('Process test', function(assert) {
+
+ var vertices = [Ember.Object.create({
+ name: "v1"
+ }), Ember.Object.create({
+ name: "v2"
+ }), Ember.Object.create({
+ name: "v3"
+ }), Ember.Object.create({
+ name: "v4"
+ })];
+ vertices.firstObject = {
+ dag: {
+ edges: [{
+ inputVertexName: "v1",
+ outputVertexName: "v3"
+ }, {
+ inputVertexName: "v2",
+ outputVertexName: "v3"
+ }, {
+ inputVertexName: "v3",
+ outputVertexName: "v4"
+ }]
+ }
+ };
+
+ let controller = this.subject({
+ send: Ember.K,
+ beforeSort: {bind: Ember.K},
+ initVisibleColumns: Ember.K,
+ getCounterColumns: function () {
+ return [];
+ },
+ model: vertices
+ });
+
+ var processes = controller.get("processes");
+
+ assert.equal(processes[2].blockers[0].vertex, vertices[0]);
+ assert.equal(processes[2].blockers[1].vertex, vertices[1]);
+ assert.equal(processes[3].blockers[0].vertex, vertices[2]);
});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js b/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js
new file mode 100644
index 0000000..ffab868
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/unit/utils/process-test.js
@@ -0,0 +1,147 @@
+/**
+ * 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.
+ */
+
+import Process from '../../../utils/process';
+import { module, test } from 'qunit';
+
+module('Unit | Utility | process');
+
+test('Basic creation test', function(assert) {
+ let process = Process.create();
+
+ assert.ok(process);
+ assert.ok(process.getColor);
+ assert.ok(process.startEvent);
+ assert.ok(process.endEvent);
+ assert.ok(process.getAllBlockers);
+});
+
+test('getColor test', function(assert) {
+ let process = Process.create();
+
+ assert.equal(process.getColor(), "#0");
+
+ process.set("color", {
+ h: 10,
+ s: 20,
+ l: 30
+ });
+ assert.equal(process.getColor(), "hsl( 10, 20%, 30% )");
+ assert.equal(process.getColor(0.2), "hsl( 10, 20%, 40% )");
+});
+
+test('startEvent test', function(assert) {
+ let process = Process.create();
+
+ assert.equal(process.get("startEvent"), undefined);
+
+ process.set("events", [{
+ time: 50,
+ }, {
+ time: 70,
+ }, {
+ time: 20,
+ }, {
+ time: 80,
+ }]);
+ assert.equal(process.get("startEvent").time, 20);
+
+ process.set("events", [{
+ time: 50,
+ }, {
+ time: 70,
+ }, {
+ time: 80,
+ }]);
+ assert.equal(process.get("startEvent").time, 50);
+});
+
+test('endEvent test', function(assert) {
+ let process = Process.create();
+
+ assert.equal(process.get("endEvent"), undefined);
+
+ process.set("events", [{
+ time: 50,
+ }, {
+ time: 70,
+ }, {
+ time: 20,
+ }, {
+ time: 80,
+ }]);
+ assert.equal(process.get("endEvent").time, 80);
+
+ process.set("events", [{
+ time: 50,
+ }, {
+ time: 70,
+ }, {
+ time: 20,
+ }]);
+ assert.equal(process.get("endEvent").time, 70);
+});
+
+test('getAllBlockers test', function(assert) {
+ var cyclicProcess = Process.create({
+ name: "p3",
+ });
+ cyclicProcess.blockers = [cyclicProcess];
+
+ var multiLevelCycle1 = Process.create({
+ name: "p5",
+ });
+ var multiLevelCycle2 = Process.create({
+ name: "p6",
+ });
+ multiLevelCycle1.blockers = [multiLevelCycle2];
+ multiLevelCycle2.blockers = [multiLevelCycle1];
+
+ var process = Process.create({
+ blockers: [Process.create({
+ name: "p1"
+ }), Process.create({
+ name: "p2",
+ blockers: [Process.create({
+ name: "p21"
+ }), Process.create({
+ name: "p22",
+ blockers: [Process.create({
+ name: "p221"
+ })]
+ })]
+ }), cyclicProcess, Process.create({
+ name: "p4"
+ }), multiLevelCycle1]
+ });
+
+ var all = process.getAllBlockers();
+
+ assert.equal(all.length, 9);
+
+ assert.equal(all[0].get("name"), "p1");
+ assert.equal(all[1].get("name"), "p2");
+ assert.equal(all[2].get("name"), "p21");
+ assert.equal(all[3].get("name"), "p22");
+ assert.equal(all[4].get("name"), "p221");
+ assert.equal(all[5].get("name"), "p3");
+ assert.equal(all[6].get("name"), "p4");
+ assert.equal(all[7].get("name"), "p5");
+ assert.equal(all[8].get("name"), "p6");
+
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/c9c7d809/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js b/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js
new file mode 100644
index 0000000..85c0d0f
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/unit/utils/vertex-process-test.js
@@ -0,0 +1,98 @@
+/**
+ * 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.
+ */
+
+import VertexProcess from '../../../utils/vertex-process';
+import { module, test } from 'qunit';
+
+import Ember from 'ember';
+
+module('Unit | Utility | vertex process');
+
+test('Basic creation test', function(assert) {
+ let process = VertexProcess.create();
+
+ assert.ok(process);
+
+ assert.ok(process.name);
+ assert.ok(process.completeTime);
+ assert.ok(process.blockingEventName);
+
+ assert.ok(process.events);
+ assert.ok(process.unblockTime);
+});
+
+test('unblockTime test', function(assert) {
+ var process = VertexProcess.create();
+ assert.equal(process.get("unblockTime"), undefined);
+
+ process = VertexProcess.create({
+ blockers: [VertexProcess.create({
+ vertex: {
+ endTime: 10
+ }
+ }), VertexProcess.create({
+ vertex: {
+ endTime: 15
+ }
+ }), VertexProcess.create({
+ vertex: {
+ endTime: 20
+ }
+ })]
+ });
+
+ assert.ok(process.get("unblockTime"), 20);
+
+ process.blockers[2].set("vertex", Ember.Object.create({
+ endTime: 12
+ }));
+ assert.ok(process.get("unblockTime"), 15);
+
+ process.blockers[2].vertex.set("endTime", 25);
+ assert.ok(process.get("unblockTime"), 25);
+});
+
+test('events test', function(assert) {
+ var process = VertexProcess.create({
+ vertex: Ember.Object.create({
+ events: [{
+ eventtype: "testEvent1"
+ },{
+ eventtype: "testEvent2"
+ }],
+ firstTaskStartTime: 10,
+ lastTaskFinishTime: 20
+ })
+ });
+
+ assert.equal(process.get("events.length"), 4);
+
+ assert.equal(process.get("events.0.name"), "testEvent1");
+ assert.equal(process.get("events.1.name"), "testEvent2");
+ assert.equal(process.get("events.2.time"), 10);
+ assert.equal(process.get("events.3.time"), 20);
+
+ process.set("blockers", [VertexProcess.create({
+ vertex: {
+ endTime: 30
+ }
+ })]);
+
+ assert.equal(process.get("events.length"), 5);
+ assert.equal(process.get("events.4.time"), 30);
+});