seafoam 0.5 → 0.9
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.
- checksums.yaml +4 -4
- data/bin/bgv2isabelle +1 -5
- data/bin/bgv2json +1 -5
- data/bin/cfg2asm +1 -5
- data/bin/seafoam +1 -5
- data/lib/seafoam/bgv/bgv_parser.rb +10 -2
- data/lib/seafoam/commands.rb +53 -32
- data/lib/seafoam/graal/pi.rb +18 -0
- data/lib/seafoam/graph.rb +33 -1
- data/lib/seafoam/graphviz_writer.rb +24 -2
- data/lib/seafoam/json_writer.rb +1 -3
- data/lib/seafoam/{annotators → passes}/fallback.rb +4 -4
- data/lib/seafoam/{annotators → passes}/graal.rb +43 -13
- data/lib/seafoam/passes/truffle.rb +58 -0
- data/lib/seafoam/passes.rb +61 -0
- data/lib/seafoam/version.rb +1 -1
- data/lib/seafoam.rb +5 -4
- metadata +32 -66
- data/.github/probots.yml +0 -2
- data/.github/workflows/workflows.yml +0 -39
- data/.gitignore +0 -7
- data/.rubocop.yml +0 -37
- data/.ruby-version +0 -1
- data/.seafoam/config +0 -1
- data/CODE_OF_CONDUCT.md +0 -128
- data/CONTRIBUTING.md +0 -5
- data/Gemfile +0 -2
- data/LICENSE.md +0 -7
- data/README.md +0 -378
- data/demos/box-unbox-stats +0 -65
- data/docs/annotators.md +0 -43
- data/docs/bgv.md +0 -293
- data/docs/getting-graphs.md +0 -59
- data/docs/images/igv.png +0 -0
- data/docs/images/seafoam.png +0 -0
- data/docs/images/spotlight-igv.png +0 -0
- data/docs/images/spotlight-seafoam.png +0 -0
- data/docs/json.md +0 -35
- data/examples/Fib.java +0 -24
- data/examples/MatMult.java +0 -39
- data/examples/fib-java.bgv.gz +0 -0
- data/examples/fib.js +0 -15
- data/examples/fib.rb +0 -15
- data/examples/identity.rb +0 -13
- data/examples/java/Irreducible.class +0 -0
- data/examples/java/Irreducible.j +0 -35
- data/examples/java/IrreducibleDecompiled.java +0 -21
- data/examples/java/JavaExamples.java +0 -418
- data/examples/matmult.rb +0 -29
- data/examples/overflow.rb +0 -13
- data/examples/ruby/clamps.rb +0 -20
- data/examples/ruby/graal.patch +0 -15
- data/examples/ruby/ruby_examples.rb +0 -278
- data/lib/seafoam/annotators.rb +0 -54
- data/lib/seafoam/config.rb +0 -34
- data/seafoam.gemspec +0 -21
- data/spec/seafoam/annotators/fallback_spec.rb +0 -69
- data/spec/seafoam/annotators/graal_spec.rb +0 -96
- data/spec/seafoam/annotators_spec.rb +0 -61
- data/spec/seafoam/bgv/bgv_parser_spec.rb +0 -157
- data/spec/seafoam/binary/io_binary_reader_spec.rb +0 -176
- data/spec/seafoam/cfg/cfg_parser_spec.rb +0 -21
- data/spec/seafoam/cfg/disassembler_spec.rb +0 -32
- data/spec/seafoam/command_spec.rb +0 -316
- data/spec/seafoam/graph_spec.rb +0 -172
- data/spec/seafoam/graphviz_writer_spec.rb +0 -63
- data/spec/seafoam/json_writer_spec.rb +0 -14
- data/spec/seafoam/spec_helpers.rb +0 -34
- data/spec/seafoam/spotlight_spec.rb +0 -38
- data/tools/render-all +0 -36
@@ -1,316 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
require 'tempfile'
|
3
|
-
|
4
|
-
require 'seafoam'
|
5
|
-
|
6
|
-
require 'rspec'
|
7
|
-
|
8
|
-
describe Seafoam::Commands do
|
9
|
-
before :all do
|
10
|
-
@fib_java = File.expand_path('../../examples/fib-java.bgv', __dir__)
|
11
|
-
@fib_ruby = File.expand_path('../../examples/fib-ruby.bgv', __dir__)
|
12
|
-
end
|
13
|
-
|
14
|
-
before :each do
|
15
|
-
@out = StringIO.new
|
16
|
-
@commands = Seafoam::Commands.new(@out, {})
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '#info' do
|
20
|
-
it 'prints format and version' do
|
21
|
-
@commands.send :info, @fib_java
|
22
|
-
lines = @out.string.lines.map(&:rstrip)
|
23
|
-
expect(lines.first).to eq 'BGV 7.0'
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'does not work on a graph' do
|
27
|
-
expect { @commands.send :info, "#{@fib_java}:0" }.to raise_error(ArgumentError)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '#list' do
|
32
|
-
it 'prints graphs' do
|
33
|
-
@commands.send :list, @fib_java
|
34
|
-
lines = @out.string.lines.map(&:rstrip)
|
35
|
-
expect(lines.take(5)).to eq [
|
36
|
-
"#{@fib_java}:0 2:Fib.fib(int)/After phase org.graalvm.compiler.java.GraphBuilderPhase",
|
37
|
-
"#{@fib_java}:1 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.PhaseSuite",
|
38
|
-
"#{@fib_java}:2 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.DeadCodeEliminationPhase",
|
39
|
-
"#{@fib_java}:3 2:Fib.fib(int)/After parsing",
|
40
|
-
"#{@fib_java}:4 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.CanonicalizerPhase"
|
41
|
-
]
|
42
|
-
expect(lines.drop(lines.length - 5)).to eq [
|
43
|
-
"#{@fib_java}:49 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.DeadCodeEliminationPhase",
|
44
|
-
"#{@fib_java}:50 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase",
|
45
|
-
"#{@fib_java}:51 2:Fib.fib(int)/After phase org.graalvm.compiler.phases.schedule.SchedulePhase",
|
46
|
-
"#{@fib_java}:52 2:Fib.fib(int)/After phase org.graalvm.compiler.core.phases.LowTier",
|
47
|
-
"#{@fib_java}:53 2:Fib.fib(int)/After low tier"
|
48
|
-
]
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'does not work on a graph' do
|
52
|
-
expect { @commands.send :list, "#{@fib_java}:0" }.to raise_error(ArgumentError)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#search' do
|
57
|
-
it 'finds terms in files' do
|
58
|
-
@commands.send :search, @fib_java, 'MethodCallTarget'
|
59
|
-
lines = @out.string.lines.map(&:rstrip)
|
60
|
-
expect(lines.take(5)).to eq [
|
61
|
-
"#{@fib_java}:0:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
62
|
-
"#{@fib_java}:0:17 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
63
|
-
"#{@fib_java}:1:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
64
|
-
"#{@fib_java}:1:17 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
65
|
-
"#{@fib_java}:2:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir..."
|
66
|
-
]
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'finds terms in graphs' do
|
70
|
-
@commands.send :search, "#{@fib_java}:0", 'MethodCallTarget'
|
71
|
-
lines = @out.string.lines.map(&:rstrip)
|
72
|
-
expect(lines).to eq [
|
73
|
-
"#{@fib_java}:0:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
74
|
-
"#{@fib_java}:0:17 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir..."
|
75
|
-
]
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'is case-insensitive' do
|
79
|
-
@commands.send :search, @fib_java, 'methodcalltarget'
|
80
|
-
lines = @out.string.lines.map(&:rstrip)
|
81
|
-
expect(lines.take(5)).to eq [
|
82
|
-
"#{@fib_java}:0:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
83
|
-
"#{@fib_java}:0:17 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
84
|
-
"#{@fib_java}:1:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
85
|
-
"#{@fib_java}:1:17 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir...",
|
86
|
-
"#{@fib_java}:2:12 ...class\":\"org.graalvm.compiler.nodes.java.MethodCallTargetNode\",\"name_template\":\"\",\"inputs\":[{\"dir..."
|
87
|
-
]
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'does not work on a node' do
|
91
|
-
expect { @commands.send :search, "#{@fib_java}:0:0" }.to raise_error(ArgumentError)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe '#edges' do
|
96
|
-
it 'prints the number of edges and nodes for a graph' do
|
97
|
-
@commands.send :edges, "#{@fib_java}:0"
|
98
|
-
lines = @out.string.lines.map(&:rstrip)
|
99
|
-
expect(lines.first).to eq '22 nodes, 30 edges'
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'prints the edges for a node' do
|
103
|
-
@commands.send :edges, "#{@fib_java}:0:13"
|
104
|
-
lines = @out.string.lines.map(&:rstrip)
|
105
|
-
expect(lines).to eq [
|
106
|
-
'Input:',
|
107
|
-
' 13 (Call Fib.fib) <-() 6 (Begin)',
|
108
|
-
' 13 (Call Fib.fib) <-() 14 (FrameState Fib#fib Fib.java:20)',
|
109
|
-
' 13 (Call Fib.fib) <-() 12 (MethodCallTarget)',
|
110
|
-
'Output:',
|
111
|
-
' 13 (Call Fib.fib) ->() 18 (Call Fib.fib)',
|
112
|
-
' 13 (Call Fib.fib) ->(values) 14 (FrameState Fib#fib Fib.java:20)',
|
113
|
-
' 13 (Call Fib.fib) ->(values) 19 (FrameState Fib#fib Fib.java:20)',
|
114
|
-
' 13 (Call Fib.fib) ->(x) 20 (+)'
|
115
|
-
]
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'prints details for an edge' do
|
119
|
-
@commands.send :edges, "#{@fib_java}:0:13-18"
|
120
|
-
lines = @out.string.lines.map(&:rstrip)
|
121
|
-
expect(lines.first).to eq '13 (Call Fib.fib) ->() 18 (Call Fib.fib)'
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'does not work on a file' do
|
125
|
-
expect { @commands.send :edges, @fib_java }.to raise_error(ArgumentError)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe '#props' do
|
130
|
-
it 'prints properties for a file' do
|
131
|
-
@commands.send :props, @fib_java
|
132
|
-
expect(@out.string.gsub(/\n\n/, "\n")).to eq "{\n \"vm.uuid\": \"28729\"\n}\n"
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'prints properties for a graph' do
|
136
|
-
@commands.send :props, "#{@fib_java}:0"
|
137
|
-
lines = @out.string.lines.map(&:rstrip)
|
138
|
-
expect(lines[3]).to include '"name": "2:Fib.fib(int)"'
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'prints properties for a node' do
|
142
|
-
@commands.send :props, "#{@fib_java}:0:13"
|
143
|
-
lines = @out.string.lines.map(&:rstrip)
|
144
|
-
expect(lines[3]).to include '"declaring_class": "Fib"'
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'prints properties for an edge' do
|
148
|
-
@commands.send :props, "#{@fib_java}:0:13-18"
|
149
|
-
lines = @out.string.lines.map(&:rstrip)
|
150
|
-
expect(lines[2]).to include '"name": "next"'
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe '#source' do
|
155
|
-
it 'prints source information for a node' do
|
156
|
-
@commands.send :source, "#{@fib_ruby}:8:2443"
|
157
|
-
expect(@out.string).to eq <<~SOURCE
|
158
|
-
java.lang.Math#addExact
|
159
|
-
org.truffleruby.core.numeric.IntegerNodes$AddNode#add
|
160
|
-
org.truffleruby.core.numeric.IntegerNodesFactory$AddNodeFactory$AddNodeGen#executeAdd
|
161
|
-
org.truffleruby.core.inlined.InlinedAddNode#intAdd
|
162
|
-
org.truffleruby.core.inlined.InlinedAddNodeGen#execute
|
163
|
-
org.truffleruby.language.control.IfElseNode#execute
|
164
|
-
org.truffleruby.language.control.SequenceNode#execute
|
165
|
-
org.truffleruby.language.arguments.CheckArityNode#execute
|
166
|
-
org.truffleruby.language.control.SequenceNode#execute
|
167
|
-
org.truffleruby.language.methods.CatchForMethodNode#execute
|
168
|
-
org.truffleruby.language.methods.ExceptionTranslatingNode#execute
|
169
|
-
org.truffleruby.language.RubyRootNode#execute
|
170
|
-
org.graalvm.compiler.truffle.runtime.OptimizedCallTarget#executeRootNode
|
171
|
-
org.graalvm.compiler.truffle.runtime.OptimizedCallTarget#profiledPERoot
|
172
|
-
SOURCE
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
describe '#render' do
|
177
|
-
it 'does not work on a file' do
|
178
|
-
expect { @commands.send :render, @fib_java }.to raise_error(ArgumentError)
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'can render all BGV files to dot' do
|
182
|
-
Seafoam::SpecHelpers::SAMPLE_BGV.each do |file|
|
183
|
-
@commands.send :render, "#{file}:7", '--out', 'out.dot'
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
if Seafoam::SpecHelpers.dependencies_installed?
|
188
|
-
it 'supports -o out.pdf' do
|
189
|
-
@commands.send :render, "#{@fib_java}:0", '--out', 'out.pdf'
|
190
|
-
expect(`file out.pdf`).to start_with 'out.pdf: PDF document'
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'supports -o out.svg' do
|
194
|
-
@commands.send :render, "#{@fib_java}:0", '--out', 'out.svg'
|
195
|
-
expect(`file out.svg`).to start_with 'out.svg: SVG Scalable Vector Graphics image'
|
196
|
-
end
|
197
|
-
|
198
|
-
it 'supports -o out.png' do
|
199
|
-
@commands.send :render, "#{@fib_java}:0", '--out', 'out.png'
|
200
|
-
expect(`file out.png`).to start_with 'out.png: PNG image data'
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'supports -o out.dot' do
|
204
|
-
@commands.send :render, "#{@fib_java}:0", '--out', 'out.dot'
|
205
|
-
expect(`file out.dot`).to start_with 'out.dot: ASCII text'
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'supports spotlighting nodes' do
|
209
|
-
@commands.send :render, "#{@fib_java}:0", '--spotlight', '13'
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'does not work on a node' do
|
213
|
-
expect { @commands.send :render, "#{@fib_java}:0:13" }.to raise_error(ArgumentError)
|
214
|
-
end
|
215
|
-
else
|
216
|
-
it 'raises an exception if Graphviz is not installed' do
|
217
|
-
expect do
|
218
|
-
@commands.send :render, "#{@fib_java}:0", '--out', 'out.pdf'
|
219
|
-
end.to raise_error(RuntimeError, /Could not run Graphviz - is it installed?/)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe '#cfg2asm' do
|
225
|
-
if Seafoam::SpecHelpers.dependencies_installed?
|
226
|
-
it 'prints format and version' do
|
227
|
-
@commands.cfg2asm(File.expand_path('../../examples/java/exampleWhile.cfg', __dir__), '--no-comments')
|
228
|
-
lines = @out.string.lines.map(&:rstrip)
|
229
|
-
expect(lines[1]).to include "0x117df59e0:\tnop dword ptr [rax + rax]"
|
230
|
-
expect(lines[-1]).to include "0x117df5a47:\thlt"
|
231
|
-
end
|
232
|
-
else
|
233
|
-
it 'raises an exception if Capstone is not installed' do
|
234
|
-
expect do
|
235
|
-
@commands.cfg2asm(File.expand_path('../../examples/java/exampleWhile.cfg', __dir__), '--no-comments')
|
236
|
-
end.to raise_error(RuntimeError, /Could not load Capstone - is it installed?/)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
describe '#debug' do
|
242
|
-
it 'does not work with a graph' do
|
243
|
-
expect { @commands.send :debug, "#{@fib_java}:0" }.to raise_error(ArgumentError)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
describe '#help' do
|
248
|
-
it 'does not take any arguments' do
|
249
|
-
expect { @commands.send :seafoam, '--help', 'foo' }.to raise_error(ArgumentError)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
describe '#version' do
|
254
|
-
it 'does not take any arguments' do
|
255
|
-
expect { @commands.send :version, 'foo' }.to raise_error(ArgumentError)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
describe '#parse_name' do
|
260
|
-
it 'parses file.bgv' do
|
261
|
-
file, graph, node, edge = @commands.send(:parse_name, 'file.bgv')
|
262
|
-
expect(file).to eq 'file.bgv'
|
263
|
-
expect(graph).to be_nil
|
264
|
-
expect(node).to be_nil
|
265
|
-
expect(edge).to be_nil
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'parses file.bgv:14' do
|
269
|
-
file, graph, node, edge = @commands.send(:parse_name, 'file.bgv:14')
|
270
|
-
expect(file).to eq 'file.bgv'
|
271
|
-
expect(graph).to eq 14
|
272
|
-
expect(node).to be_nil
|
273
|
-
expect(edge).to be_nil
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'parses file.bgv:14:12' do
|
277
|
-
file, graph, node, edge = @commands.send(:parse_name, 'file.bgv:14:12')
|
278
|
-
expect(file).to eq 'file.bgv'
|
279
|
-
expect(graph).to eq 14
|
280
|
-
expect(node).to eq 12
|
281
|
-
expect(edge).to be_nil
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'parses file.bgv:14:12-81' do
|
285
|
-
file, graph, node, edge = @commands.send(:parse_name, 'file.bgv:14:12-81')
|
286
|
-
expect(file).to eq 'file.bgv'
|
287
|
-
expect(graph).to eq 14
|
288
|
-
expect(node).to eq 12
|
289
|
-
expect(edge).to eq 81
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'parses a realistic knarly BGV file name' do
|
293
|
-
file, graph, node, edge = @commands.send(:parse_name, '../graal_dumps/2019.11.03.19.35.03.828/TruffleHotSpotCompilation-13320[while_loop_at__Users_chrisseaton_src_github.com_Shopify_truffleruby-shopify_src_main_ruby_truffleruby_core_kernel.rb:360<OSR>].bgv:14:12-81')
|
294
|
-
expect(file).to eq '../graal_dumps/2019.11.03.19.35.03.828/TruffleHotSpotCompilation-13320[while_loop_at__Users_chrisseaton_src_github.com_Shopify_truffleruby-shopify_src_main_ruby_truffleruby_core_kernel.rb:360<OSR>].bgv'
|
295
|
-
expect(graph).to eq 14
|
296
|
-
expect(node).to eq 12
|
297
|
-
expect(edge).to eq 81
|
298
|
-
end
|
299
|
-
|
300
|
-
it 'parses a BGV file name with periods and colons' do
|
301
|
-
file, graph, node, edge = @commands.send(:parse_name, 'TruffleHotSpotCompilation-13029[Truffle::ThreadOperations.detect_recursion_<split-3a5973bc>].bgv:4')
|
302
|
-
expect(file).to eq 'TruffleHotSpotCompilation-13029[Truffle::ThreadOperations.detect_recursion_<split-3a5973bc>].bgv'
|
303
|
-
expect(graph).to eq 4
|
304
|
-
expect(node).to be_nil
|
305
|
-
expect(edge).to be_nil
|
306
|
-
end
|
307
|
-
|
308
|
-
it 'parses a BGV.gz file name with periods and colons' do
|
309
|
-
file, graph, node, edge = @commands.send(:parse_name, 'TruffleHotSpotCompilation-13029[Truffle::ThreadOperations.detect_recursion_<split-3a5973bc>].bgv.gz:4')
|
310
|
-
expect(file).to eq 'TruffleHotSpotCompilation-13029[Truffle::ThreadOperations.detect_recursion_<split-3a5973bc>].bgv.gz'
|
311
|
-
expect(graph).to eq 4
|
312
|
-
expect(node).to be_nil
|
313
|
-
expect(edge).to be_nil
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
data/spec/seafoam/graph_spec.rb
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
require 'seafoam'
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
|
5
|
-
describe Seafoam::Graph do
|
6
|
-
describe '#initialize' do
|
7
|
-
it 'set properties' do
|
8
|
-
graph = Seafoam::Graph.new(a: 12)
|
9
|
-
expect(graph.props[:a]).to eq 12
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe '#create_node' do
|
14
|
-
it 'adds a node to the graph' do
|
15
|
-
graph = Seafoam::Graph.new
|
16
|
-
node = graph.create_node(14)
|
17
|
-
expect(graph.nodes.values).to include node
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'set properties' do
|
21
|
-
graph = Seafoam::Graph.new
|
22
|
-
node = graph.create_node(14, a: 12)
|
23
|
-
expect(node.props[:a]).to eq 12
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'returns the node' do
|
27
|
-
graph = Seafoam::Graph.new
|
28
|
-
node = graph.create_node(14)
|
29
|
-
expect(node.id).to eq 14
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#create_edge' do
|
34
|
-
it 'adds an edge to the graph' do
|
35
|
-
graph = Seafoam::Graph.new
|
36
|
-
from = graph.create_node(14)
|
37
|
-
to = graph.create_node(2)
|
38
|
-
edge = graph.create_edge(from, to)
|
39
|
-
expect(graph.edges).to include edge
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'set properties' do
|
43
|
-
graph = Seafoam::Graph.new
|
44
|
-
from = graph.create_node(14)
|
45
|
-
to = graph.create_node(2)
|
46
|
-
edge = graph.create_edge(from, to, a: 12)
|
47
|
-
expect(edge.props[:a]).to eq 12
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'returns the edge' do
|
51
|
-
graph = Seafoam::Graph.new
|
52
|
-
from = graph.create_node(14)
|
53
|
-
to = graph.create_node(2)
|
54
|
-
edge = graph.create_edge(from, to)
|
55
|
-
expect(edge.from).to eq from
|
56
|
-
expect(edge.to).to eq to
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe Seafoam::Node do
|
62
|
-
describe '#inputs' do
|
63
|
-
it 'returns only input edges' do
|
64
|
-
graph = Seafoam::Graph.new
|
65
|
-
node_a = graph.create_node(1)
|
66
|
-
node_b = graph.create_node(2)
|
67
|
-
node_c = graph.create_node(3)
|
68
|
-
node_d = graph.create_node(4)
|
69
|
-
in_edge = graph.create_edge(node_a, node_b)
|
70
|
-
out_edge = graph.create_edge(node_b, node_c)
|
71
|
-
unrelated_edge = graph.create_edge(node_c, node_d)
|
72
|
-
expect(node_b.inputs).to include in_edge
|
73
|
-
expect(node_b.inputs).to_not include out_edge
|
74
|
-
expect(node_b.inputs).to_not include unrelated_edge
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe '#outputs' do
|
79
|
-
it 'returns only output edges' do
|
80
|
-
graph = Seafoam::Graph.new
|
81
|
-
node_a = graph.create_node(1)
|
82
|
-
node_b = graph.create_node(2)
|
83
|
-
node_c = graph.create_node(3)
|
84
|
-
node_d = graph.create_node(4)
|
85
|
-
in_edge = graph.create_edge(node_a, node_b)
|
86
|
-
out_edge = graph.create_edge(node_b, node_c)
|
87
|
-
unrelated_edge = graph.create_edge(node_c, node_d)
|
88
|
-
expect(node_b.outputs).to_not include in_edge
|
89
|
-
expect(node_b.outputs).to include out_edge
|
90
|
-
expect(node_b.outputs).to_not include unrelated_edge
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe '#edges' do
|
95
|
-
it 'returns both input and output edges' do
|
96
|
-
graph = Seafoam::Graph.new
|
97
|
-
node_a = graph.create_node(1)
|
98
|
-
node_b = graph.create_node(2)
|
99
|
-
node_c = graph.create_node(3)
|
100
|
-
node_d = graph.create_node(4)
|
101
|
-
in_edge = graph.create_edge(node_a, node_b)
|
102
|
-
out_edge = graph.create_edge(node_b, node_c)
|
103
|
-
unrelated_edge = graph.create_edge(node_c, node_d)
|
104
|
-
expect(node_b.edges).to include in_edge
|
105
|
-
expect(node_b.edges).to include out_edge
|
106
|
-
expect(node_b.edges).to_not include unrelated_edge
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe '#adjacent' do
|
111
|
-
it 'returns nodes from both input and output edges' do
|
112
|
-
graph = Seafoam::Graph.new
|
113
|
-
node_a = graph.create_node(1)
|
114
|
-
node_b = graph.create_node(2)
|
115
|
-
node_c = graph.create_node(3)
|
116
|
-
node_d = graph.create_node(4)
|
117
|
-
graph.create_edge node_a, node_b
|
118
|
-
graph.create_edge node_b, node_c
|
119
|
-
graph.create_edge node_c, node_d
|
120
|
-
expect(node_b.adjacent).to include node_a
|
121
|
-
expect(node_b.adjacent).to include node_c
|
122
|
-
expect(node_b.adjacent).to_not include node_d
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe '#id_and_label' do
|
127
|
-
it 'returns an id and label if there is one' do
|
128
|
-
node = Seafoam::Node.new(14, label: 'foo')
|
129
|
-
expect(node.id_and_label).to eq '14 (foo)'
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'returns just an id if there is no label' do
|
133
|
-
node = Seafoam::Node.new(14)
|
134
|
-
expect(node.id_and_label).to eq '14'
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe Seafoam::Edge do
|
140
|
-
describe '#from' do
|
141
|
-
it 'returns the from node' do
|
142
|
-
graph = Seafoam::Graph.new
|
143
|
-
node_a = graph.create_node(1)
|
144
|
-
node_b = graph.create_node(2)
|
145
|
-
edge = graph.create_edge(node_a, node_b)
|
146
|
-
expect(edge.from).to eq node_a
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
describe '#to' do
|
151
|
-
it 'returns the to node' do
|
152
|
-
graph = Seafoam::Graph.new
|
153
|
-
node_a = graph.create_node(1)
|
154
|
-
node_b = graph.create_node(2)
|
155
|
-
edge = graph.create_edge(node_a, node_b)
|
156
|
-
expect(edge.to).to eq node_b
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
describe '#nodes' do
|
161
|
-
it 'returns both the from and to node' do
|
162
|
-
graph = Seafoam::Graph.new
|
163
|
-
node_a = graph.create_node(1)
|
164
|
-
node_b = graph.create_node(2)
|
165
|
-
node_c = graph.create_node(3)
|
166
|
-
edge = graph.create_edge(node_a, node_b)
|
167
|
-
expect(edge.nodes).to include node_a
|
168
|
-
expect(edge.nodes).to include node_b
|
169
|
-
expect(edge.nodes).to_not include node_c
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
|
-
require 'seafoam'
|
4
|
-
|
5
|
-
require 'rspec'
|
6
|
-
|
7
|
-
require_relative 'spec_helpers'
|
8
|
-
|
9
|
-
describe Seafoam::GraphvizWriter do
|
10
|
-
describe '#write_graph' do
|
11
|
-
before :all do
|
12
|
-
file = File.expand_path('../../examples/fib-java.bgv', __dir__)
|
13
|
-
parser = Seafoam::BGV::BGVParser.new(file)
|
14
|
-
parser.read_file_header
|
15
|
-
parser.read_graph_preheader
|
16
|
-
parser.read_graph_header
|
17
|
-
@fib_java_graph = parser.read_graph
|
18
|
-
end
|
19
|
-
|
20
|
-
before :each do
|
21
|
-
@stream = StringIO.new
|
22
|
-
@writer = Seafoam::GraphvizWriter.new(@stream)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'writes the header' do
|
26
|
-
@writer.write_graph @fib_java_graph
|
27
|
-
expect(@stream.string).to start_with 'digraph G {'
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'writes all graphs' do
|
31
|
-
Seafoam::SpecHelpers::SAMPLE_BGV.each do |file|
|
32
|
-
parser = Seafoam::BGV::BGVParser.new(file)
|
33
|
-
parser.read_file_header
|
34
|
-
parser.skip_document_props
|
35
|
-
parser.skip_document_props
|
36
|
-
loop do
|
37
|
-
index, = parser.read_graph_preheader
|
38
|
-
break unless index
|
39
|
-
|
40
|
-
parser.read_graph_header
|
41
|
-
@writer.write_graph parser.read_graph
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '#quote' do
|
48
|
-
it 'adds quotes' do
|
49
|
-
writer = Seafoam::GraphvizWriter.new(nil)
|
50
|
-
expect(writer.send(:quote, 'foo')).to eq '"foo"'
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'escapes an existing quote' do
|
54
|
-
writer = Seafoam::GraphvizWriter.new(nil)
|
55
|
-
expect(writer.send(:quote, 'foo"bar')).to eq '"foo\"bar"'
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'escapes an existing escape' do
|
59
|
-
writer = Seafoam::GraphvizWriter.new(nil)
|
60
|
-
expect(writer.send(:quote, 'foo\bar')).to eq '"foo\\bar"'
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'seafoam'
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
|
5
|
-
require_relative 'spec_helpers'
|
6
|
-
|
7
|
-
describe Seafoam::JSONWriter do
|
8
|
-
describe '#prepare_json' do
|
9
|
-
it 'transforms a NaN to the string [NaN]' do
|
10
|
-
writer = Seafoam::JSONWriter.new(nil)
|
11
|
-
expect(writer.send(:prepare_json, { a: 1.0, b: Float::NAN, c: 2.0 })).to eq({ a: 1.0, b: '[NaN]', c: 2.0 })
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Seafoam
|
2
|
-
module SpecHelpers
|
3
|
-
SAMPLE_BGV = [
|
4
|
-
'fib-java.bgv',
|
5
|
-
'fib-js.bgv',
|
6
|
-
'fib-ruby.bgv',
|
7
|
-
'matmult-java.bgv',
|
8
|
-
'matmult-ruby.bgv'
|
9
|
-
].map { |f| File.expand_path("../../examples/#{f}", __dir__) }
|
10
|
-
|
11
|
-
def self.example_graph(file, graph_index)
|
12
|
-
file = File.expand_path("../../examples/#{file}.bgv", __dir__)
|
13
|
-
parser = Seafoam::BGV::BGVParser.new(file)
|
14
|
-
parser.read_file_header
|
15
|
-
parser.skip_document_props
|
16
|
-
loop do
|
17
|
-
index, = parser.read_graph_preheader
|
18
|
-
raise unless index
|
19
|
-
|
20
|
-
if index == graph_index
|
21
|
-
parser.read_graph_header
|
22
|
-
break parser.read_graph
|
23
|
-
else
|
24
|
-
parser.skip_graph_header
|
25
|
-
parser.skip_graph
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.dependencies_installed?
|
31
|
-
ENV['NO_DEPENDENCIES_INSTALLED'].nil?
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'seafoam'
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
|
5
|
-
describe Seafoam::Spotlight do
|
6
|
-
before :each do
|
7
|
-
file = File.expand_path('../../examples/fib-java.bgv', __dir__)
|
8
|
-
parser = Seafoam::BGV::BGVParser.new(file)
|
9
|
-
parser.read_file_header
|
10
|
-
parser.skip_document_props
|
11
|
-
parser.read_graph_preheader
|
12
|
-
parser.read_graph_header
|
13
|
-
@graph = parser.read_graph
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'marks individual nodes as lit' do
|
17
|
-
spotlight = Seafoam::Spotlight.new(@graph)
|
18
|
-
spotlight.light @graph.nodes[13]
|
19
|
-
expect(@graph.nodes[13].props[:spotlight]).to eq 'lit'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'marks surrounding nodes as shaded' do
|
23
|
-
spotlight = Seafoam::Spotlight.new(@graph)
|
24
|
-
spotlight.light @graph.nodes[13]
|
25
|
-
expect(@graph.nodes.values
|
26
|
-
.select { |n| n.props[:spotlight] == 'shaded' }
|
27
|
-
.map(&:id).sort).to eq [6, 12, 14, 18, 19, 20]
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'marks other nodes as hidden' do
|
31
|
-
spotlight = Seafoam::Spotlight.new(@graph)
|
32
|
-
spotlight.light @graph.nodes[13]
|
33
|
-
spotlight.shade
|
34
|
-
expect(@graph.nodes.values
|
35
|
-
.select { |n| n.props[:hidden] }
|
36
|
-
.map(&:id).sort).to eq [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 21]
|
37
|
-
end
|
38
|
-
end
|
data/tools/render-all
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$LOAD_PATH.push File.expand_path('../lib', __dir__)
|
4
|
-
require 'seafoam'
|
5
|
-
|
6
|
-
config = Seafoam::Config.new
|
7
|
-
commands = Seafoam::Commands.new($stdout, config)
|
8
|
-
|
9
|
-
extra = {
|
10
|
-
'exampleArrayRead' => [42],
|
11
|
-
'exampleDoubleSynchronized' => [48, 49],
|
12
|
-
'exampleFieldRead' => [42],
|
13
|
-
'exampleFullEscape' => [33],
|
14
|
-
'exampleInstanceOfManyImpls' => [65],
|
15
|
-
'exampleInstanceOfOneImpl' => [65],
|
16
|
-
'exampleInterfaceCallOneImpl' => [9],
|
17
|
-
'exampleInterfaceCallManyImpls' => [9],
|
18
|
-
'exampleLocalSynchronized' => [33],
|
19
|
-
'exampleNoEscape' => [33],
|
20
|
-
'examplePartialEscape' => [33],
|
21
|
-
'exampleUnsafeRead' => [42]
|
22
|
-
}
|
23
|
-
|
24
|
-
Dir.glob(File.expand_path('../examples/java/*.bgv', __dir__)).each do |bgv|
|
25
|
-
basename = File.basename(bgv, '.bgv')
|
26
|
-
phases = [6]
|
27
|
-
phases.push(*(extra[basename] || []))
|
28
|
-
extra_options = []
|
29
|
-
if basename == 'exampleLocalVariablesState'
|
30
|
-
extra_options.push '--show-frame-state'
|
31
|
-
end
|
32
|
-
phases.each do |phase|
|
33
|
-
commands.seafoam "#{bgv}:#{phase}", 'render', *extra_options, '--out', File.expand_path("../#{basename}@#{phase}.png", __dir__)
|
34
|
-
commands.seafoam "#{bgv}:#{phase}", 'render', *extra_options, '--out', File.expand_path("../#{basename}@#{phase}.svg", __dir__)
|
35
|
-
end
|
36
|
-
end
|