1 : /*
2 : Copyright (c) 2011, Yahoo! Inc.
3 : All rights reserved.
4 :
5 : Redistribution and use of this software in source and binary forms,
6 : with or without modification, are permitted provided that the following
7 : conditions are met:
8 :
9 : * Redistributions of source code must retain the above
10 : copyright notice, this list of conditions and the
11 : following disclaimer.
12 :
13 : * Redistributions in binary form must reproduce the above
14 : copyright notice, this list of conditions and the
15 : following disclaimer in the documentation and/or other
16 : materials provided with the distribution.
17 :
18 : * Neither the name of Yahoo! Inc. nor the names of its
19 : contributors may be used to endorse or promote products
20 : derived from this software without specific prior
21 : written permission of Yahoo! Inc.
22 :
23 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 : IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 : TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26 : PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 : */
35 :
36 :
37 1 : module.exports = {
38 : Create: function(hub, common) {
39 : // Javascript is single threaded! We don't have to worry about concurrency!
40 1 : var TEST_TIME_THRESHOLD = 60000, // 60 seconds to wait before declaring test dead
41 : BROWSER_TIME_THRESHOLD = 20000, // Delete a captured browser after it has been gone for this long - 20 seconds
42 : ERROR = '<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="BROWSER" tests="0" failures="1" time="0">Test Timed Out: Most likely a Javascript parsing error - try loading URL in your browser</testsuite></testsuites>',
43 : path = require('path')
44 : ;
45 :
46 : // Events I care about
47 1 : hub.addListener('action:prune', prune);
48 :
49 1 : function prune(doing_what, req, cache) {
50 5 : var redirect;
51 5 : if (doing_what != 'status') {
52 4 : prune_browsers(req, cache);
53 4 : redirect = prune_tests(doing_what, req, cache);
54 4 : hub.emit('pruneDone', redirect);
55 : }
56 : }
57 :
58 1 : function prune_tests(doing_what, req, cache) {
59 4 : var now = new Date().getTime(),
60 : browser = req.session.uuid, test,
61 : timeStarted;
62 :
63 4 : for (var i = 0; i< cache.tests_to_run.length; i++) {
64 3 : test = cache.tests_to_run[i];
65 3 : timeStarted = test.running;
66 3 : if (timeStarted) {
67 1 : if (now - timeStarted > TEST_TIME_THRESHOLD) {
68 : // This test has been running for too long!!
69 1 : hub.emit(hub.LOG, hub.ERROR, "Test running for too long - killing it");
70 1 : cache.tests_to_run.splice(i, 1);
71 1 : if (test.sendOutput) {
72 0 : hub.emit('sendOutput', test.sendOutput, test.url + ' timed out - javascript error?');
73 : }
74 :
75 : // Dump a FAILED XML file
76 : // Use test file name as the NAME of this test (vs. component name from test itself)
77 1 : var parts = test.url.split('/');
78 1 : var name = parts.pop();
79 1 : name = name.replace(/\..*$/, ''); // get rid of suffix
80 1 : var names = common.makeSaneNames(common.browserName(req));
81 1 : var err = ERROR;
82 1 : err = err.replace('BROWSER', names[1]);
83 1 : err = err.replace('URL', test.url);
84 1 : var params = { results: err, name: name };
85 :
86 1 : hub.emit(hub.log, hub.ERROR, "Dumped error unit test file " + name + " / " + names[0] + " (from " + test.url + ")");
87 1 : common.dumpFile(params, 'results', names[0] + '-test.xml', name);
88 :
89 1 : if (cache.browsers[browser]) {
90 1 : cache.browsers[browser].heart_beat = now;
91 1 : cache.browsers[browser].get_test = now;
92 1 : return 1; //Redirect!
93 : }
94 : }
95 : } else {
96 : // make sure browser is still requesting tests
97 2 : if (cache.browsers[browser]) {
98 2 : var last_got_test = cache.browsers[browser].get_test;
99 2 : if (doing_what != 'get_test' && (now - last_got_test > TEST_TIME_THRESHOLD)) {
100 1 : hub.emit(hub.LOG, hub.ERROR, "Been too long since you've requested a test: " + browser + " - Kicking iframe...");
101 1 : return 1; // Redirect!!
102 : }
103 : }
104 : }
105 : }
106 : }
107 :
108 1 : function prune_browsers(req, cache) {
109 4 : var now = new Date().getTime(), me = req.session.uuid;
110 :
111 4 : if (typeof cache.browsers == 'object') {
112 4 : for (browser in cache.browsers) {
113 5 : if (browser == me) continue;
114 :
115 2 : var b_time = cache.browsers[browser].heart_beat;
116 2 : if (now - b_time > BROWSER_TIME_THRESHOLD) {
117 1 : hub.emit(hub.LOG, hub.ERROR, "We lost browser " + cache.browsers[browser].name);
118 1 : delete cache.browsers[browser];
119 : // take it out of ay tests it's supposed to be running
120 1 : for (var i = 0; i < cache.tests_to_run.length; i++) {
121 1 : var test = cache.tests_to_run[i];
122 1 : if (test.browser == browser) {
123 : // blow this test out!
124 1 : cache.tests_to_run.splice(i, 1);
125 1 : i--; // fake a perl 'redo'!! Otherwise we might skip over something!
126 : }
127 : }
128 : }
129 : }
130 : }
131 : }
132 : }
133 : };
134 :
|