bullring 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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