node-marshal 0.2.1 → 0.2.2

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.
@@ -1,137 +1,137 @@
1
- require_relative '../lib/node-marshal.rb'
2
- require 'test/unit'
3
-
4
- # Wrapper for Ruby Proc class (Proc and lambdas) that
5
- # saves the text representation of the function
6
- class TestFunc
7
- def initialize(text)
8
- @text = text.to_s
9
- @value = eval(text)
10
- end
11
-
12
- def to_s
13
- @text
14
- end
15
-
16
- def inspect
17
- @text
18
- end
19
-
20
- def call(x,a)
21
- @value.(x,a)
22
- end
23
- end
24
-
25
- # Class for generation of the complex structure that includes:
26
- # Hashes, Arrays, Floats, Fixnums, Ranges, Strings, Symbols, Procs
27
- # It is used for node testing
28
- class TestHashTree
29
- attr_reader :value, :depth
30
- def initialize(*args)
31
- if args.length == 2
32
- rnd = Random.new
33
- lambdas = ['->x,a{a*x**2 + 2*x + 1}', '->x,a{Math::sin(a) + x**2 * a**0.5}']
34
- data_size, depth = args[0], args[1]
35
- @depth = depth
36
- @value = {:depth => depth, :data => [], :leaves =>[] }
37
- data_size.times do
38
- case rnd.rand(30000) % 7
39
- when 0
40
- @value[:data] << 10**(rnd.rand(600000) * 0.001 - 300)
41
- when 1
42
- @value[:data] << rnd.rand(2**31 - 1)
43
- when 2
44
- rndstr = (Array.new(25) { (rnd.rand(127 - 32) + 32).chr }).join
45
- @value[:data] << rndstr
46
- when 3
47
- @value[:data] << TestFunc.new(lambdas[rnd.rand(30000) % lambdas.length])
48
- when 4
49
- a, b = rnd.rand(100), rnd.rand(10)
50
- @value[:data] << (a..(a + b))
51
- when 5
52
- a, b = rnd.rand(100), rnd.rand(10)
53
- @value[:data] << (a...(a + b))
54
- when 6
55
- rndsym = (Random.rand(1_000_000_000).to_s(36)).to_sym
56
- @value[:data] << rndsym
57
- else
58
- nil
59
- end
60
- end
61
-
62
- if depth > 0
63
- 3.times do
64
- @value[:leaves] << TestHashTree.new(data_size, depth - 1)
65
- end
66
- end
67
- elsif args.length == 1
68
- h = args[0]
69
- raise(ArgumentError, 'Input argument must be a hash') if !h.is_a?(Hash)
70
- @depth = h[:depth]
71
- @value = {
72
- :depth => @depth,
73
- :data => h[:data].map {|x| (x.class == String) ? x.dup : x },
74
- :leaves => h[:leaves].map {|x| TestHashTree.new(x)}}
75
- else
76
- raise ArgumentError, 'Invalid numer of arguments'
77
- end
78
- end
79
-
80
- def to_s
81
- @value.to_s
82
- end
83
-
84
- def inspect
85
- self.to_s
86
- end
87
- # Recursive comparison of two complex structures
88
- def ==(val)
89
- if (self.depth != val.depth) ||
90
- (self.value[:data].length != val.value[:data].length)
91
- return false
92
- else
93
- # Compare data
94
- res = true
95
- v1, v2 = self.value[:data], val.value[:data]
96
- v1.each_index do |ind|
97
- if (v1[ind].class != Proc && v1[ind].class != TestFunc)
98
- res = false if v1[ind] != v2[ind]
99
- else
100
- x, a = 1.2345, 1.5
101
- y1, y2 = v1[ind].call(x,a), v2[ind].call(x,a)
102
- res = false if y1 != y2
103
- end
104
- end
105
- # Compare leaves
106
- p1, p2 = self.value[:leaves], val.value[:leaves]
107
- p1.each_index {|ind| res = false if p1[ind] != p2[ind] }
108
- return res
109
- end
110
- end
111
- end
112
-
113
- # Tests that check the processing of large and/or complex nodes
114
- class TestComplex < Test::Unit::TestCase
115
- def test_bruteforce
116
- # Create test tree, turn it to node and save it to disk
117
- puts 'Creating the tree...'
118
- tree_src = TestHashTree.new(20, 7);
119
- puts 'Dumping the node...'
120
- tree_str = tree_src.to_s
121
- node = NodeMarshal.new(:srcmemory, tree_str)
122
- tree_bin = node.to_bin
123
- puts node.inspect
124
-
125
- File.open('node.bin', 'wb') {|fp| fp << tree_bin }
126
- puts " Source code size: %d bytes" % tree_str.length
127
- puts " Binary data size: %d bytes" % tree_bin.length
128
- # Clear the memory
129
- node = nil; GC.enable; GC.start
130
- # Load the node from the disk and turn it to tree
131
- puts 'Loading the node...'
132
- node = NodeMarshal.new(:binfile, 'node.bin')
133
- puts node.inspect
134
- tree_dest = TestHashTree.new(node.compile.eval)
135
- assert_equal(tree_src, tree_dest)
136
- end
1
+ require_relative '../lib/node-marshal.rb'
2
+ require 'test/unit'
3
+
4
+ # Wrapper for Ruby Proc class (Proc and lambdas) that
5
+ # saves the text representation of the function
6
+ class TestFunc
7
+ def initialize(text)
8
+ @text = text.to_s
9
+ @value = eval(text)
10
+ end
11
+
12
+ def to_s
13
+ @text
14
+ end
15
+
16
+ def inspect
17
+ @text
18
+ end
19
+
20
+ def call(x,a)
21
+ @value.(x,a)
22
+ end
23
+ end
24
+
25
+ # Class for generation of the complex structure that includes:
26
+ # Hashes, Arrays, Floats, Fixnums, Ranges, Strings, Symbols, Procs
27
+ # It is used for node testing
28
+ class TestHashTree
29
+ attr_reader :value, :depth
30
+ def initialize(*args)
31
+ if args.length == 2
32
+ rnd = Random.new
33
+ lambdas = ['->x,a{a*x**2 + 2*x + 1}', '->x,a{Math::sin(a) + x**2 * a**0.5}']
34
+ data_size, depth = args[0], args[1]
35
+ @depth = depth
36
+ @value = {:depth => depth, :data => [], :leaves =>[] }
37
+ data_size.times do
38
+ case rnd.rand(30000) % 7
39
+ when 0
40
+ @value[:data] << 10**(rnd.rand(600000) * 0.001 - 300)
41
+ when 1
42
+ @value[:data] << rnd.rand(2**31 - 1)
43
+ when 2
44
+ rndstr = (Array.new(25) { (rnd.rand(127 - 32) + 32).chr }).join
45
+ @value[:data] << rndstr
46
+ when 3
47
+ @value[:data] << TestFunc.new(lambdas[rnd.rand(30000) % lambdas.length])
48
+ when 4
49
+ a, b = rnd.rand(100), rnd.rand(10)
50
+ @value[:data] << (a..(a + b))
51
+ when 5
52
+ a, b = rnd.rand(100), rnd.rand(10)
53
+ @value[:data] << (a...(a + b))
54
+ when 6
55
+ rndsym = (Random.rand(1_000_000_000).to_s(36)).to_sym
56
+ @value[:data] << rndsym
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ if depth > 0
63
+ 3.times do
64
+ @value[:leaves] << TestHashTree.new(data_size, depth - 1)
65
+ end
66
+ end
67
+ elsif args.length == 1
68
+ h = args[0]
69
+ raise(ArgumentError, 'Input argument must be a hash') if !h.is_a?(Hash)
70
+ @depth = h[:depth]
71
+ @value = {
72
+ :depth => @depth,
73
+ :data => h[:data].map {|x| (x.class == String) ? x.dup : x },
74
+ :leaves => h[:leaves].map {|x| TestHashTree.new(x)}}
75
+ else
76
+ raise ArgumentError, 'Invalid numer of arguments'
77
+ end
78
+ end
79
+
80
+ def to_s
81
+ @value.to_s
82
+ end
83
+
84
+ def inspect
85
+ self.to_s
86
+ end
87
+ # Recursive comparison of two complex structures
88
+ def ==(val)
89
+ if (self.depth != val.depth) ||
90
+ (self.value[:data].length != val.value[:data].length)
91
+ return false
92
+ else
93
+ # Compare data
94
+ res = true
95
+ v1, v2 = self.value[:data], val.value[:data]
96
+ v1.each_index do |ind|
97
+ if (v1[ind].class != Proc && v1[ind].class != TestFunc)
98
+ res = false if v1[ind] != v2[ind]
99
+ else
100
+ x, a = 1.2345, 1.5
101
+ y1, y2 = v1[ind].call(x,a), v2[ind].call(x,a)
102
+ res = false if y1 != y2
103
+ end
104
+ end
105
+ # Compare leaves
106
+ p1, p2 = self.value[:leaves], val.value[:leaves]
107
+ p1.each_index {|ind| res = false if p1[ind] != p2[ind] }
108
+ return res
109
+ end
110
+ end
111
+ end
112
+
113
+ # Tests that check the processing of large and/or complex nodes
114
+ class TestComplex < Test::Unit::TestCase
115
+ def test_bruteforce
116
+ # Create test tree, turn it to node and save it to disk
117
+ puts 'Creating the tree...'
118
+ tree_src = TestHashTree.new(20, 7);
119
+ puts 'Dumping the node...'
120
+ tree_str = tree_src.to_s
121
+ node = NodeMarshal.new(:srcmemory, tree_str)
122
+ tree_bin = node.to_bin
123
+ puts node.inspect
124
+
125
+ File.open('node.bin', 'wb') {|fp| fp << tree_bin }
126
+ puts " Source code size: %d bytes" % tree_str.length
127
+ puts " Binary data size: %d bytes" % tree_bin.length
128
+ # Clear the memory
129
+ node = nil; GC.enable; GC.start
130
+ # Load the node from the disk and turn it to tree
131
+ puts 'Loading the node...'
132
+ node = NodeMarshal.new(:binfile, 'node.bin')
133
+ puts node.inspect
134
+ tree_dest = TestHashTree.new(node.compile.eval)
135
+ assert_equal(tree_src, tree_dest)
136
+ end
137
137
  end
@@ -1,68 +1,68 @@
1
- require_relative '../lib/node-marshal.rb'
2
- require 'test/unit'
3
-
4
- # Set of tests for Convay's life game running and compilation
5
- # (includes tests with binary Ruby files)
6
- class TestLifeGame < Test::Unit::TestCase
7
- # Compile and launch life game with different
8
- # compiler options (requires zlib library)
9
-
10
- def test_compile
11
- compile_with_opts(nil)
12
- compile_with_opts(:compress=>true)
13
- end
14
- # Test life game with glider gun configuration
15
- def test_glider_gun
16
- # Compile the class to the instuction sequence
17
- bin = NodeMarshal.new(:srcfile, 'lifegame.rb')
18
- puts bin.inspect
19
- bin.compile.eval
20
- # Calculate the life game
21
- res_node = run_game
22
- # Play the game of life without NodeMarshal
23
- Object.send(:remove_const, :LifeGame)
24
- load('lifegame.rb')
25
- res_load = run_game
26
- # Compare the results
27
- assert_equal(res_node, res_load)
28
- Object.send(:remove_const, :LifeGame)
29
- puts res_load
30
- end
31
-
32
- # Runs Life game initialized with "glider gun" configuration
33
- # and makes 75 turns (changes of generations)
34
- def run_game
35
- g = LifeGame::Grid.new(25, 80)
36
- g.cfg_glider!
37
- g.cfg_glider_gun!
38
- 75.times {g.make_step!}
39
- g.to_ascii
40
- end
41
-
42
- # Compiles Convay's life game using proposed options
43
- # (opts is a Hash, see NodeMarshal#compile_rb_file method)
44
- def compile_with_opts(opts)
45
- stub = <<-EOS
46
- g = LifeGame::Grid.new(25, 80)
47
- g.cfg_glider_gun!
48
- 75.times {g.make_step!}
49
- File.open('life.res', 'w') {|fp| fp << g.to_ascii }
50
- EOS
51
- # Compile Life game to the file and obtain the result
52
- if opts == nil
53
- NodeMarshal.compile_rb_file('lifegame_bin.rb', 'lifegame.rb')
54
- else
55
- NodeMarshal.compile_rb_file('lifegame_bin.rb', 'lifegame.rb', opts)
56
- end
57
- txt = File.read('lifegame_bin.rb') + stub
58
- File.open('lifegame_bin.rb', 'w') {|fp| fp << txt }
59
- `ruby lifegame_bin.rb`
60
- res_file = File.read('life.res')
61
- `rm life.res`
62
- # Run the life game without compilation to the file
63
- load('lifegame.rb')
64
- res_load = run_game
65
- Object.send(:remove_const, :LifeGame)
66
- assert_equal(res_file, res_load)
67
- end
68
- end
1
+ require_relative '../lib/node-marshal.rb'
2
+ require 'test/unit'
3
+
4
+ # Set of tests for Convay's life game running and compilation
5
+ # (includes tests with binary Ruby files)
6
+ class TestLifeGame < Test::Unit::TestCase
7
+ # Compile and launch life game with different
8
+ # compiler options (requires zlib library)
9
+
10
+ def test_compile
11
+ compile_with_opts(nil)
12
+ compile_with_opts(:compress=>true)
13
+ end
14
+ # Test life game with glider gun configuration
15
+ def test_glider_gun
16
+ # Compile the class to the instuction sequence
17
+ bin = NodeMarshal.new(:srcfile, 'lifegame.rb')
18
+ puts bin.inspect
19
+ bin.compile.eval
20
+ # Calculate the life game
21
+ res_node = run_game
22
+ # Play the game of life without NodeMarshal
23
+ Object.send(:remove_const, :LifeGame)
24
+ load('lifegame.rb')
25
+ res_load = run_game
26
+ # Compare the results
27
+ assert_equal(res_node, res_load)
28
+ Object.send(:remove_const, :LifeGame)
29
+ puts res_load
30
+ end
31
+
32
+ # Runs Life game initialized with "glider gun" configuration
33
+ # and makes 75 turns (changes of generations)
34
+ def run_game
35
+ g = LifeGame::Grid.new(25, 80)
36
+ g.cfg_glider!
37
+ g.cfg_glider_gun!
38
+ 75.times {g.make_step!}
39
+ g.to_ascii
40
+ end
41
+
42
+ # Compiles Convay's life game using proposed options
43
+ # (opts is a Hash, see NodeMarshal#compile_rb_file method)
44
+ def compile_with_opts(opts)
45
+ stub = <<-EOS
46
+ g = LifeGame::Grid.new(25, 80)
47
+ g.cfg_glider_gun!
48
+ 75.times {g.make_step!}
49
+ File.open('life.res', 'w') {|fp| fp << g.to_ascii }
50
+ EOS
51
+ # Compile Life game to the file and obtain the result
52
+ if opts == nil
53
+ NodeMarshal.compile_rb_file('lifegame_bin.rb', 'lifegame.rb')
54
+ else
55
+ NodeMarshal.compile_rb_file('lifegame_bin.rb', 'lifegame.rb', opts)
56
+ end
57
+ txt = File.read('lifegame_bin.rb') + stub
58
+ File.open('lifegame_bin.rb', 'w') {|fp| fp << txt }
59
+ `ruby lifegame_bin.rb`
60
+ res_file = File.read('life.res')
61
+ `rm life.res`
62
+ # Run the life game without compilation to the file
63
+ load('lifegame.rb')
64
+ res_load = run_game
65
+ Object.send(:remove_const, :LifeGame)
66
+ assert_equal(res_file, res_load)
67
+ end
68
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: UTF-8
2
+ require_relative '../lib/node-marshal.rb'
3
+ require 'test/unit'
4
+
5
+
6
+ # This unit tests Ruby 2.0 named arguments support
7
+ class TestNamedArg < Test::Unit::TestCase
8
+ def test_namedarg
9
+ # For Ruby 2.1 and higher
10
+ program_21 = %q{
11
+ def testfunc(x, foo:, bar: 'default', stuff:)
12
+ x.to_s + " " + foo.to_s + " " + bar.to_s + " " + stuff.to_s
13
+ end
14
+ def blockfunc(&block)
15
+ block.call(foo: 'bar')
16
+ end
17
+
18
+ blockstr = blockfunc do |foo:|
19
+ foo
20
+ end
21
+
22
+ testfunc(1, foo: 'a', stuff: 1e5) + "\n" +
23
+ testfunc(1, stuff: -50, foo: 'a', bar: 1.23e10) + "\n" + blockstr + "\n"
24
+ }
25
+ # For Ruby 2.0
26
+ program_20 = %q{
27
+ def testfunc(x, bar: 'default')
28
+ x.to_s + " " + bar.to_s
29
+ end
30
+ testfunc(1) + "\n" + testfunc(1, bar: 'default')
31
+ }
32
+ # Detect version of Ruby
33
+ ver = RUBY_VERSION
34
+ ver = (ver[0] + ver[2] + ver[4]).to_i
35
+ # Version-specific stuff
36
+ program = ""
37
+ if ver >= 210
38
+ program = program_21
39
+ elsif ver >= 210
40
+ program = program_20
41
+ else
42
+ assert_equal(false, true, "Ruby 2.0 or higher is required for named arguments test")
43
+ end
44
+ # Test source code compilation
45
+ node = NodeMarshal.new(:srcmemory, program)
46
+ node.show_offsets = true
47
+ #puts node.dump_tree_short
48
+ bindump = node.to_bin
49
+ node = NodeMarshal.new(:binmemory, bindump)
50
+ res_node = node.compile.eval
51
+ res_text = eval(program)
52
+ assert_equal(res_text, res_node)
53
+ end
54
+ end