bullring 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +38 -0
  3. data/Rakefile +38 -0
  4. data/lib/bullring.rb +135 -0
  5. data/lib/bullring/js/bullring.js +64 -0
  6. data/lib/bullring/js/jslint.js +6393 -0
  7. data/lib/bullring/js/jslint.min.js +171 -0
  8. data/lib/bullring/util/drubied_process.rb +66 -0
  9. data/lib/bullring/util/exceptions.rb +17 -0
  10. data/lib/bullring/util/network.rb +29 -0
  11. data/lib/bullring/version.rb +3 -0
  12. data/lib/bullring/worker.rb +36 -0
  13. data/lib/bullring/workers/rhino_server.rb +172 -0
  14. data/lib/bullring/workers/rhino_server.sh +46 -0
  15. data/lib/bullring/workers/rhino_server_worker.rb +79 -0
  16. data/lib/bullring/workers/rhino_simple_worker.rb +0 -0
  17. data/lib/scripts/server_console.sh +22 -0
  18. data/lib/tasks/bullring_tasks.rake +10 -0
  19. data/test/bullring_test.rb +301 -0
  20. data/test/dummy/README.rdoc +261 -0
  21. data/test/dummy/Rakefile +7 -0
  22. data/test/dummy/app/assets/javascripts/application.js +15 -0
  23. data/test/dummy/app/assets/javascripts/home.js +2 -0
  24. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  25. data/test/dummy/app/assets/stylesheets/home.css +4 -0
  26. data/test/dummy/app/assets/stylesheets/scaffold.css +56 -0
  27. data/test/dummy/app/controllers/application_controller.rb +3 -0
  28. data/test/dummy/app/controllers/home_controller.rb +5 -0
  29. data/test/dummy/app/helpers/application_helper.rb +2 -0
  30. data/test/dummy/app/helpers/home_helper.rb +2 -0
  31. data/test/dummy/app/views/home/index.html.erb +4 -0
  32. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  33. data/test/dummy/config.ru +4 -0
  34. data/test/dummy/config/application.rb +56 -0
  35. data/test/dummy/config/boot.rb +10 -0
  36. data/test/dummy/config/database.yml +25 -0
  37. data/test/dummy/config/environment.rb +5 -0
  38. data/test/dummy/config/environments/development.rb +37 -0
  39. data/test/dummy/config/environments/production.rb +67 -0
  40. data/test/dummy/config/environments/test.rb +37 -0
  41. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  42. data/test/dummy/config/initializers/inflections.rb +15 -0
  43. data/test/dummy/config/initializers/mime_types.rb +5 -0
  44. data/test/dummy/config/initializers/quiet_assets.rb +11 -0
  45. data/test/dummy/config/initializers/secret_token.rb +7 -0
  46. data/test/dummy/config/initializers/session_store.rb +8 -0
  47. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/test/dummy/config/locales/en.yml +5 -0
  49. data/test/dummy/config/routes.rb +60 -0
  50. data/test/dummy/log/development.log +27 -0
  51. data/test/dummy/log/test.log +0 -0
  52. data/test/dummy/public/404.html +26 -0
  53. data/test/dummy/public/422.html +26 -0
  54. data/test/dummy/public/500.html +25 -0
  55. data/test/dummy/public/favicon.ico +0 -0
  56. data/test/dummy/script/rails +6 -0
  57. data/test/test_helper.rb +4 -0
  58. metadata +213 -0
@@ -0,0 +1,46 @@
1
+ #!/bin/sh
2
+
3
+ # Usage: bullring_server.sh GEM_ROOT_DIR ARGS_FOR_RUBY_CALL
4
+
5
+ BULLRING_ROOT=$1
6
+ DAEMON_CMD=$2
7
+ PORT=$3
8
+ INIT_HEAP_SIZE=$4 # Xms, e.g. 128m
9
+ MAX_HEAP_SIZE=$5 # Xmx, e.g. 128m
10
+ YOUNG_HEAP_SIZE=$6 # Xmn, e.g. 92m
11
+
12
+ # Load RVM into a shell session *as a function*
13
+ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
14
+
15
+ # First try to load from a user install
16
+ source "$HOME/.rvm/scripts/rvm"
17
+
18
+ elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
19
+
20
+ # Then try to load from a root install
21
+ source "/usr/local/rvm/scripts/rvm"
22
+
23
+ else
24
+
25
+ printf "ERROR: An RVM installation was not found.\n"
26
+
27
+ fi
28
+
29
+ export JAVA_OPTS="-Djava.net.preferIPv4Stack=true"
30
+
31
+ rhino_gem_dir=`bundle show therubyrhino`
32
+
33
+ rvm use jruby
34
+ ruby_bin=`which ruby`
35
+
36
+ GEM_HOME=
37
+ IRBRC=
38
+ BUNDLE_GEMFILE=
39
+ GEM_PATH=
40
+ RUBYOPT=
41
+ BUNDLE_BIN_PATH=
42
+
43
+ $ruby_bin -J-Xmn$YOUNG_HEAP_SIZE -J-Xms$INIT_HEAP_SIZE -J-Xmx$MAX_HEAP_SIZE \
44
+ -J-server \
45
+ -I $rhino_gem_dir/lib \
46
+ $BULLRING_ROOT/bullring/workers/rhino_server.rb $DAEMON_CMD $PORT
@@ -0,0 +1,79 @@
1
+ require 'bullring/util/drubied_process'
2
+
3
+ module Bullring
4
+
5
+ class RhinoServerWorker < Bullring::Worker
6
+
7
+ def discard
8
+ # Daemons.run(server_command, stop_options)
9
+ # @server.kill if !@server.nil?
10
+ # DRb.stop_service
11
+ # @server = nil
12
+ end
13
+
14
+ def initialize
15
+ # TODO add development environment switch here so that developers
16
+ # can just use therubyracer (or rhino or whatever) directly
17
+ # If already using jruby, can also just use rhino directly
18
+
19
+ options = {}
20
+ options[:process] = {
21
+ :host => 'localhost',
22
+ :port => Bullring.configuration.server_port,
23
+ :command => File.join(Bullring.root, "/bullring/workers/rhino_server.sh"),
24
+ :args => [Bullring.root,
25
+ "start",
26
+ "#{Bullring.configuration.server_port}",
27
+ Bullring.configuration.jvm_init_heap_size,
28
+ Bullring.configuration.jvm_max_heap_size,
29
+ Bullring.configuration.jvm_young_heap_size]
30
+ }
31
+
32
+ @server = DrubiedProcess.new(options)
33
+
34
+ @server.configure({:run_timeout_secs => Bullring.configuration.execution_timeout_secs,
35
+ :logger => Bullring.logger})
36
+ end
37
+
38
+ # TODO important! this guy needs to know if the daemon crashed and restarted (so that it
39
+ # can repopulate its library scripts; alternatively, we could pass the library scripts
40
+ # in on the command line, in which case the restarting would pick them up)
41
+
42
+ def add_library(script)
43
+ # this guy needs to maintain the library scripts in case the daemon restarts
44
+ server.add_library(script)
45
+ end
46
+
47
+ def add_library_file(filename)
48
+ server.add_library_script(filename)
49
+ end
50
+
51
+ def check(script, options)
52
+ server.check(script, options)
53
+ end
54
+
55
+ def run(script, options)
56
+ begin
57
+ result = server.run(script, options)
58
+ result.respond_to?(:to_h) ? result.to_h : result
59
+ rescue DRb::DRbUnknownError => e
60
+ raise e.unknown
61
+ rescue Bullring::JSError => e
62
+ raise e
63
+ end
64
+ end
65
+
66
+ def alive?
67
+ server.alive?
68
+ end
69
+
70
+ private
71
+
72
+ attr_accessor :server
73
+
74
+ end
75
+
76
+
77
+
78
+ end
79
+
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+
3
+ # Load RVM into a shell session *as a function*
4
+ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
5
+
6
+ # First try to load from a user install
7
+ source "$HOME/.rvm/scripts/rvm"
8
+
9
+ elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
10
+
11
+ # Then try to load from a root install
12
+ source "/usr/local/rvm/scripts/rvm"
13
+
14
+ else
15
+
16
+ printf "ERROR: An RVM installation was not found.\n"
17
+
18
+ fi
19
+
20
+ rvm use jruby@bullring
21
+
22
+ irb -rubygems -I lib -r bullring/workers/rhino_server.rb
@@ -0,0 +1,10 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bullring do
3
+ # # Task goes here
4
+ # end
5
+
6
+
7
+ desc "Open an irb session preloaded with this library"
8
+ task :console do
9
+ sh "irb -rubygems -I lib -r bullring.rb"
10
+ end
@@ -0,0 +1,301 @@
1
+ require 'test_helper'
2
+ # require 'test/unit'
3
+ # require 'bullring'
4
+
5
+ class BullringTest < Test::Unit::TestCase #ActiveSupport::TestCase
6
+ test "truth" do
7
+ assert_kind_of Module, Bullring
8
+ end
9
+
10
+ test "run 1" do
11
+ assert_nothing_raised{Bullring.run("3")}
12
+ end
13
+
14
+ test "run multiline" do
15
+ assert_nothing_raised do
16
+ result = Bullring.run("3;\r\n4")
17
+ assert_equal 4, result
18
+ end
19
+ end
20
+
21
+ test 'run 2' do
22
+ code = <<-CODE
23
+ x = 'howdy';
24
+ (function(arg){return arg+' there';})(x)
25
+ CODE
26
+
27
+ assert_nothing_raised do
28
+ Bullring.run(code)
29
+ end
30
+ end
31
+
32
+ test 'run complex a' do
33
+ random_code = <<-CODE
34
+ (function(j,i,g,m,k,n,o){})([],Math,256,6,52);
35
+ CODE
36
+
37
+ assert_nothing_raised do
38
+ Bullring.run(random_code)
39
+ end
40
+ end
41
+
42
+ test 'run complex full oneline' do
43
+ random_code = <<-CODE
44
+ (function (pool, math, width, chunks, significance, overflow, startdenom) {})([], Math, 256,6,52);
45
+ CODE
46
+
47
+ assert_nothing_raised do
48
+ Bullring.run(random_code)
49
+ end
50
+ end
51
+
52
+ test 'run complex full cut' do
53
+ random_code = <<-CODE
54
+ (function (pool, math, width, chunks, significance, overflow, startdenom) {
55
+
56
+ })(
57
+ [], // pool: entropy pool starts empty
58
+ Math, // math: package containing random, pow, and seedrandom
59
+ 256, // width: each RC4 output is 0 <= x < 256
60
+ 6, // chunks: at least six RC4 outputs for each double
61
+ 52 // significance: there are 52 significant digits in a double
62
+ );
63
+ CODE
64
+
65
+ assert_nothing_raised do
66
+ Bullring.run(random_code)
67
+ end
68
+ end
69
+
70
+ test 'run 3' do
71
+ code = <<-CODE
72
+ var myFunc = function(a,b,c) {
73
+ d = a+b;
74
+ return c*d;
75
+ }
76
+
77
+ myFunc(1,2,4);
78
+ CODE
79
+
80
+ assert_nothing_raised do
81
+ result = Bullring.run(code)
82
+ assert_equal 12, result
83
+ end
84
+ end
85
+
86
+ # test 'run complex full' do
87
+ # random_code = <<-CODE
88
+ # (function (pool, math, width, chunks, significance, overflow, startdenom) {
89
+ #
90
+ #
91
+ # //
92
+ # // seedrandom()
93
+ # // This is the seedrandom function described above.
94
+ # //
95
+ # // math['seedrandom'] = function seedrandom(seed, use_entropy) {
96
+ # // var key = [];
97
+ # // var arc4;
98
+ # //
99
+ # // // Flatten the seed string or build one from local entropy if needed.
100
+ # // seed = mixkey(flatten(
101
+ # // use_entropy ? [seed, pool] :
102
+ # // arguments.length ? seed :
103
+ # // [new Date().getTime(), pool, window], 3), key);
104
+ # //
105
+ # // // Use the seed to initialize an ARC4 generator.
106
+ # // arc4 = new ARC4(key);
107
+ # //
108
+ # // // Mix the randomness into accumulated entropy.
109
+ # // mixkey(arc4.S, pool);
110
+ # //
111
+ # // // Override Math.random
112
+ # //
113
+ # // // This function returns a random double in [0, 1) that contains
114
+ # // // randomness in every bit of the mantissa of the IEEE 754 value.
115
+ # //
116
+ # // math['random'] = function random() { // Closure to return a random double:
117
+ # // var n = arc4.g(chunks); // Start with a numerator n < 2 ^ 48
118
+ # // var d = startdenom; // and denominator d = 2 ^ 48.
119
+ # // var x = 0; // and no 'extra last byte'.
120
+ # // while (n < significance) { // Fill up all significant digits by
121
+ # // n = (n + x) * width; // shifting numerator and
122
+ # // d *= width; // denominator and generating a
123
+ # // x = arc4.g(1); // new least-significant-byte.
124
+ # // }
125
+ # // while (n >= overflow) { // To avoid rounding up, before adding
126
+ # // n /= 2; // last byte, shift everything
127
+ # // d /= 2; // right using integer math until
128
+ # // x >>>= 1; // we have exactly the desired bits.
129
+ # // }
130
+ # // return (n + x) / d; // Form the number within [0, 1).
131
+ # // };
132
+ # //
133
+ # // // Return the seed that was used
134
+ # // return seed;
135
+ # // };
136
+ # //
137
+ # // //
138
+ # // // ARC4
139
+ # // //
140
+ # // // An ARC4 implementation. The constructor takes a key in the form of
141
+ # // // an array of at most (width) integers that should be 0 <= x < (width).
142
+ # // //
143
+ # // // The g(count) method returns a pseudorandom integer that concatenates
144
+ # // // the next (count) outputs from ARC4. Its return value is a number x
145
+ # // // that is in the range 0 <= x < (width ^ count).
146
+ # // //
147
+ # // /** @constructor */
148
+ # // function ARC4(key) {
149
+ # // var t, u, me = this, keylen = key.length;
150
+ # // var i = 0, j = me.i = me.j = me.m = 0;
151
+ # // me.S = [];
152
+ # // me.c = [];
153
+ # //
154
+ # // // The empty key [] is treated as [0].
155
+ # // if (!keylen) { key = [keylen++]; }
156
+ # //
157
+ # // // Set up S using the standard key scheduling algorithm.
158
+ # // while (i < width) { me.S[i] = i++; }
159
+ # // for (i = 0; i < width; i++) {
160
+ # // t = me.S[i];
161
+ # // j = lowbits(j + t + key[i % keylen]);
162
+ # // u = me.S[j];
163
+ # // me.S[i] = u;
164
+ # // me.S[j] = t;
165
+ # // }
166
+ # //
167
+ # // // The "g" method returns the next (count) outputs as one number.
168
+ # // me.g = function getnext(count) {
169
+ # // var s = me.S;
170
+ # // var i = lowbits(me.i + 1); var t = s[i];
171
+ # // var j = lowbits(me.j + t); var u = s[j];
172
+ # // s[i] = u;
173
+ # // s[j] = t;
174
+ # // var r = s[lowbits(t + u)];
175
+ # // while (--count) {
176
+ # // i = lowbits(i + 1); t = s[i];
177
+ # // j = lowbits(j + t); u = s[j];
178
+ # // s[i] = u;
179
+ # // s[j] = t;
180
+ # // r = r * width + s[lowbits(t + u)];
181
+ # // }
182
+ # // me.i = i;
183
+ # // me.j = j;
184
+ # // return r;
185
+ # // };
186
+ # // // For robust unpredictability discard an initial batch of values.
187
+ # // // See http://www.rsa.com/rsalabs/node.asp?id=2009
188
+ # // me.g(width);
189
+ # // }
190
+ # //
191
+ # // //
192
+ # // // flatten()
193
+ # // // Converts an object tree to nested arrays of strings.
194
+ # // //
195
+ # // /** @param {Object=} result
196
+ # // * @param {string=} prop
197
+ # // * @param {string=} typ */
198
+ # // function flatten(obj, depth, result, prop, typ) {
199
+ # // result = [];
200
+ # // typ = typeof(obj);
201
+ # // if (depth && typ == 'object') {
202
+ # // for (prop in obj) {
203
+ # // if (prop.indexOf('S') < 5) { // Avoid FF3 bug (local/sessionStorage)
204
+ # // try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
205
+ # // }
206
+ # // }
207
+ # // }
208
+ # // return (result.length ? result : obj + (typ != 'string' ? '\0' : ''));
209
+ # // }
210
+ # //
211
+ # // //
212
+ # // // mixkey()
213
+ # // // Mixes a string seed into a key that is an array of integers, and
214
+ # // // returns a shortened string seed that is equivalent to the result key.
215
+ # // //
216
+ # // /** @param {number=} smear
217
+ # // * @param {number=} j */
218
+ # // function mixkey(seed, key, smear, j) {
219
+ # // seed += ''; // Ensure the seed is a string
220
+ # // smear = 0;
221
+ # // for (j = 0; j < seed.length; j++) {
222
+ # // key[lowbits(j)] =
223
+ # // lowbits((smear ^= key[lowbits(j)] * 19) + seed.charCodeAt(j));
224
+ # // }
225
+ # // seed = '';
226
+ # // for (j in key) { seed += String.fromCharCode(key[j]); }
227
+ # // return seed;
228
+ # // }
229
+ # //
230
+ # // //
231
+ # // // lowbits()
232
+ # // // A quick "n mod width" for width a power of 2.
233
+ # // //
234
+ # // function lowbits(n) { return n & (width - 1); }
235
+ # //
236
+ # // //
237
+ # // // The following constants are related to IEEE 754 limits.
238
+ # // //
239
+ # // startdenom = math.pow(width, chunks);
240
+ # // significance = math.pow(2, significance);
241
+ # // overflow = significance * 2;
242
+ # //
243
+ # // //
244
+ # // // When seedrandom.js is loaded, we immediately mix a few bits
245
+ # // // from the built-in RNG into the entropy pool. Because we do
246
+ # // // not want to intefere with determinstic PRNG state later,
247
+ # // // seedrandom will not call math.random on its own again after
248
+ # // // initialization.
249
+ # // //
250
+ # // mixkey(math.random(), pool);
251
+ # //
252
+ # // // End anonymous scope, and pass initial values.
253
+ # })(
254
+ # [], // pool: entropy pool starts empty
255
+ # Math, // math: package containing random, pow, and seedrandom
256
+ # 256, // width: each RC4 output is 0 <= x < 256
257
+ # 6, // chunks: at least six RC4 outputs for each double
258
+ # 52 // significance: there are 52 significant digits in a double
259
+ # );
260
+ # CODE
261
+ #
262
+ # assert_nothing_raised do
263
+ # Bullring.run(random_code)
264
+ # end
265
+ # end
266
+
267
+ test 'run complex' do
268
+ random_code = <<-CODE
269
+ (function(j,i,g,m,k,n,o){function q(b){var e,f,a=this,c=b.length,d=0,h=a.i=a.j=a.m=0;
270
+ a.S=[];a.c=[];for(c||(b=[c++]);d<g;)a.S[d]=d++;for(d=0;d<g;d++)e=a.S[d],
271
+ h=h+e+b[d%c]&g-1,f=a.S[h],a.S[d]=f,a.S[h]=e;a.g=function(b){var c=a.S,d=a.i+1&g-1,
272
+ e=c[d],f=a.j+e&g-1,h=c[f];c[d]=h;c[f]=e;for(var i=c[e+h&g-1];--b;)d=d+1&g-1,e=c[d],
273
+ f=f+e&g-1,h=c[f],c[d]=h,c[f]=e,i=i*g+c[e+h&g-1];a.i=d;a.j=f;return i};a.g(g)}
274
+ function p(b,e,f,a,c){f=[];c=typeof b;if(e&&c=="object")for(a in b)if(a.indexOf("S")<5)
275
+ try{f.push(p(b[a],e-1))}catch(d){}return f.length?f:b+(c!="string"?"\\0":"")}
276
+ function l(b,e,f,a){b+="";for(a=f=0;a<b.length;a++){var c=e,d=a&g-1,h=(f^=e[a&g-1]*19)+
277
+ b.charCodeAt(a);c[d]=h&g-1}b="";for(a in e)b+=String.fromCharCode(e[a]);return b}
278
+ i.seedrandom=function(b,e){var f=[],a;b=l(p(e?[b,j]:arguments.length?b:[(new Date).getTime(),
279
+ j,window],3),f);a=new q(f);l(a.S,j);i.random=function(){for(var c=a.g(m),d=o,b=0;c<k;)
280
+ c=(c+b)*g,d*=g,b=a.g(1);for(;c>=n;)c/=2,d/=2,b>>>=1;return(c+b)/d};return b};o=i.pow(g,m);
281
+ k=i.pow(2,k);n=k*2;l(i.random(),j)})([],Math,256,6,52);
282
+ CODE
283
+
284
+ assert_nothing_raised do
285
+ Bullring.run(random_code)
286
+ end
287
+ end
288
+
289
+ test 'check' do
290
+ code = <<-CODE
291
+ a = 42;
292
+ y = 2*a;
293
+ CODE
294
+
295
+ assert_nothing_raised do
296
+ Bullring.check(code)
297
+ end
298
+
299
+ end
300
+
301
+ end