UNPKG

6.65 kBJavaScriptView Raw
1/*
2 * Copyright 2012 Amadeus s.a.s. Licensed under the Apache License, Version 2.0
3 * (the "License"); you may not use this file except in compliance with the
4 * License. You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 * License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15var util = require("util");
16var events = require("events");
17
18var connect = require('connect');
19//var coverageServer = require('node-coverage').admin;
20
21var Logger = require('../logging/logger.js');
22var Coverage = require('./coverage.js');
23var Resources = require('../middlewares/resources.js');
24var Browser = require('./browser.js');
25var AllTests = require('../test-type/all-tests.js');
26
27var pad2 = function (number) {
28 var res = number + "";
29 if (res.length == 1) {
30 return "0" + res;
31 } else {
32 return res;
33 }
34};
35
36var counter = 0;
37var createCampaignId = function (date) {
38 counter++;
39 return [date.getFullYear(), pad2(date.getMonth() + 1), pad2(date.getDate()), pad2(date.getHours()), pad2(date.getMinutes()), pad2(date.getSeconds()), pad2(Math.floor(Math.random() * 100)), pad2(counter)].join('');
40};
41
42var TestCampaign = function (config, parentLogger) {
43 this.results = config.liveResults ? [] : null;
44 this.startTime = new Date();
45 this.campaignNumber = config.campaignNumber;
46 this.id = createCampaignId(this.startTime);
47 this.baseURL = "/campaign" + (config.predictableUrls ? this.campaignNumber : this.id);
48 this.logger = new Logger('TestCampaign', this.campaignNumber, parentLogger);
49 this.logger.logInfo("Initializing campaign " + this.id + "...");
50
51 var rootDirectory = config.rootDirectory || "";
52 this.rootDirectory = rootDirectory;
53 this.config = config;
54
55 var browsersCfg = config.browsers;
56 if (browsersCfg && browsersCfg.length > 0) {
57 this.logger.logInfo("Expecting the following browsers to connect: ");
58 } else {
59 this.logger.logInfo("No specific browsers expected in the campaign");
60 browsersCfg = [""];
61 }
62 var browsers = [];
63 for (var i = 0, l = browsersCfg.length; i < l; i++) {
64 browsers[i] = new Browser(browsersCfg[i]);
65 if (browsers[i].name) {
66 this.logger.logInfo("- " + browsers[i].name);
67 }
68 }
69 this.browsers = browsers;
70
71 var resources = new Resources({
72 baseDirectory: rootDirectory,
73 contexts: config.resources || {}
74 }, this.logger);
75 this.resources = resources;
76
77 var coverage = null;
78 var coverageConfig = config.coverage;
79 if (coverageConfig) {
80 coverage = new Coverage(coverageConfig, this.logger, rootDirectory);
81 this.coverage = coverage;
82 }
83
84 this.tests = new AllTests(this, config.tests, this.logger);
85
86 var app = connect();
87 app.use(resources.pathResolver());
88 if (coverage) {
89 app.use(coverage.instrumentedSender());
90 }
91 app.use(resources.staticSender());
92 app.use(this.tests.handleRequest);
93
94 this.handleRequest = app.handle.bind(app);
95 this.tasks = [];
96 this.tasksTrees = [];
97 this.remainingTasks = null;
98 this.finished = false;
99 this.initFinished = false;
100};
101
102util.inherits(TestCampaign, events.EventEmitter);
103
104TestCampaign.prototype.init = function (callback) {
105 // fills the array of tasks
106 var self = this;
107 var waitingCb = 1;
108 var endInit = function () {
109 waitingCb--;
110 if (waitingCb !== 0) {
111 return;
112 }
113 self.tasks = self.tests.tasks;
114 self.tasksTrees = self.tests.tasksTrees;
115 self.remainingTasks = self.tasks.length;
116 self.addResult({
117 event: "tasksList",
118 campaignId: self.id,
119 tasks: self.tasksTrees
120 });
121 var initResults = self.tests.initResults;
122 for (var i = 0, l = initResults.length; i < l; i++) {
123 self.addResult(initResults[i]);
124 }
125 self.initFinished = true;
126 process.nextTick(callback);
127 };
128 if (this.coverage) {
129 waitingCb++;
130 this.coverage.init(endInit);
131 }
132 this.tests.init(endInit);
133};
134
135TestCampaign.prototype.addResult = function (event) {
136 if (!event.time) {
137 event.time = new Date().getTime();
138 }
139 var eventName = event.event;
140 if ((eventName == "taskFinished" && !event.restartPlanned) || eventName == "taskIgnored") {
141 this.remainingTasks--;
142 this.checkFinished();
143 }
144 if (this.results) {
145 this.results.push(event);
146 }
147 this.emit('result-' + eventName, event);
148 this.emit('result', event);
149
150};
151
152TestCampaign.prototype.checkFinished = function () {
153 if (this.remainingTasks === 0 && !this.finished && this.initFinished) {
154 var self = this;
155 process.nextTick(function () {
156 if (self.finished) {
157 return;
158 }
159 // this flag makes sure the campaignFinished event can be raised only once
160 self.finished = true;
161 self.addResult({
162 event: 'campaignFinished'
163 });
164 var elapsed = self.getElapsedTime();
165 self.logger.logInfo("Campaign finished. Time: %dmin %dsec", [elapsed.min, elapsed.sec]);
166 self.emit('finished');
167 });
168 }
169};
170
171TestCampaign.prototype.addCoverageResult = function (taskId, coverage) {
172 // taskId is not used currently, but it would be possible in the future to keep the link between a coverage result
173 // and the test which produced it, or perhaps to build, for each file, the list of tests which use it
174 if (this.coverage) {
175 this.coverage.addResult(coverage);
176 }
177 this.checkFinished();
178};
179
180TestCampaign.prototype.getCoverageResult = function () {
181 if (this.coverage) {
182 return this.coverage.getResult();
183 }
184};
185
186TestCampaign.prototype.getElapsedTime = function () {
187 var elapsedSec = Math.ceil((new Date() - this.startTime) / 1000);
188 var elapsedMin = Math.floor(elapsedSec / 60);
189 elapsedSec = elapsedSec % 60;
190 return {
191 min: elapsedMin,
192 sec: elapsedSec
193 };
194};
195
196TestCampaign.prototype.dispose = function () {
197 this.logger.logDebug("Disposing campaign " + this.id);
198
199 this.tests.dispose();
200 // No need to dispose coverage
201 this.resources.dispose();
202 // No need to dispose browsers
203
204 this.logger.dispose();
205 this.finished = true;
206};
207
208module.exports = TestCampaign;