graphs 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,225 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ require 'csv'
5
+ require_relative '../graph'
6
+
7
+ class Graph
8
+ # Returns a GDF version of the current graph
9
+ # @param opts [Hash] A customizable set of options
10
+ # @return [String]
11
+ # @see GDF.unparse
12
+ def to_gdf(opts=nil)
13
+ GDF::unparse(self, opts)
14
+ end
15
+
16
+ # Write the current graph into a GDF file. This method is used internally,
17
+ # use Graph#write instead.
18
+ # @param filename [String] a valid filename
19
+ # @return []
20
+ # @see GDF.unparse
21
+ def write_gdf(filename, opts=nil)
22
+ gdf = GDF::unparse(self, opts)
23
+ f = File.open(filename, 'w')
24
+ f.write(gdf)
25
+ f.close
26
+ end
27
+ end
28
+
29
+ # GDF-related functions
30
+ # see http://guess.wikispot.org/The_GUESS_.gdf_format
31
+ module GDF
32
+
33
+ # Node fields definition
34
+ NODEDEF = 'nodedef>'
35
+
36
+ # Edge fields definition
37
+ EDGEDEF = 'edgedef>'
38
+
39
+ # Non-string predefined node properties
40
+ PREDEFINED_NODE_PROPS = {
41
+ 'x' => 'float',
42
+ 'y' => 'float',
43
+ 'visible' => 'boolean',
44
+ 'fixed' => 'boolean',
45
+ 'style' => 'int',
46
+ 'width' => 'float',
47
+ 'height' => 'float'
48
+ }
49
+
50
+ # Non-string predefined edge properties
51
+ PREDEFINED_EDGE_PROPS = {
52
+ 'visible' => 'boolean',
53
+ 'weight' => 'float',
54
+ 'width' => 'float',
55
+ 'directed' => 'boolean',
56
+ 'labelvisible' => 'boolean'
57
+ }
58
+
59
+ # Loads a GDF file and return a new Graph object
60
+ # @param filename [String] a valid filename
61
+ # @see GDF.parse
62
+ def self.load(filename)
63
+ self.parse(File.read(filename))
64
+ end
65
+
66
+ # Parse some GDF text and return a new Graph object
67
+ # @param content [String] a valid GDF String
68
+ # @see GDF.load
69
+ # @see GDF.unparse
70
+ def self.parse(content)
71
+
72
+ if (content.nil? || content.length == 0)
73
+ return Graph.new([],[])
74
+ end
75
+
76
+ fields_split = /[\t ]*,[\t ]*/
77
+
78
+ nodedef_len, edgedef_len = NODEDEF.length, EDGEDEF.length
79
+
80
+ current_def = nil
81
+
82
+ nodes, edges = [], []
83
+ current_set = nil
84
+
85
+ content.each_line do |line|
86
+ line.strip!
87
+ is_nodedef = line.start_with? NODEDEF
88
+ is_edgedef = !is_nodedef && line.start_with?(EDGEDEF)
89
+
90
+ if is_nodedef || is_edgedef
91
+ line.slice!(0, is_nodedef ? nodedef_len : edgedef_len)
92
+ line.strip!
93
+ defaults = is_nodedef ? PREDEFINED_NODE_PROPS : PREDEFINED_EDGE_PROPS
94
+ current_def = line.split(fields_split).map do |l|
95
+ read_def(l, defaults)
96
+ end
97
+
98
+ current_set = is_nodedef ? nodes : edges
99
+ else
100
+ el = {}
101
+ fields = line.parse_csv || [nil]
102
+ fields.zip(current_def).each do |val,label_type|
103
+ label, type, default = label_type
104
+ el[label] = parse_field(val, type, default)
105
+ end
106
+ current_set << el
107
+ end
108
+ end
109
+
110
+ Graph.new(nodes, edges)
111
+ end
112
+
113
+ # Return a GDF String which describe the given Graph
114
+ # @param graph [Graph]
115
+ # @param opts [Hash] A customizable set of options
116
+ # @return [String]
117
+ # @see Graph#write
118
+ def self.unparse(graph, opts=nil)
119
+ # nodes
120
+ gdf_s = NODEDEF
121
+
122
+ if (graph.nodes.length == 0)
123
+ return gdf_s
124
+ end
125
+
126
+ keys = graph.nodes[0].keys
127
+ nodedef = keys.map { |k| [k, self.get_type(graph.nodes[0][k], opts)] }
128
+
129
+ gdf_s += (nodedef.map {|nd| nd.join(' ')}).join(',') + "\n"
130
+
131
+ graph.nodes.each do |n|
132
+ gdf_s += n.values.to_csv
133
+ end
134
+
135
+ # edges
136
+ gdf_s += EDGEDEF
137
+
138
+ return gdf_s if graph.edges.empty?
139
+
140
+ keys = graph.edges[0].keys
141
+ edgedef = keys.map { |k| [k, self.get_type(graph.edges[0][k], opts)] }
142
+
143
+ gdf_s += (edgedef.map {|ed| ed.join(' ')}).join(',') + "\n"
144
+
145
+ graph.edges.each do |e|
146
+ gdf_s += e.values.to_csv
147
+ end
148
+
149
+ gdf_s
150
+ end
151
+
152
+ private
153
+
154
+ # Read the value of a node/edge field, and return the value's
155
+ # type (String)
156
+ # @param v
157
+ # @param opts [Hash]
158
+ # @return [String]
159
+ def self.get_type(v, opts=nil)
160
+ opts = opts || {}
161
+
162
+ if v.is_a?(Fixnum) || v.is_a?(Bignum)
163
+ if opts[:gephi] || v <= 2147483647
164
+ return 'INT'
165
+ else
166
+ return 'BIGINT'
167
+ end
168
+ elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
169
+ return 'BOOLEAN'
170
+ elsif v.is_a?(Float)
171
+ return 'FLOAT'
172
+ else
173
+ return 'VARCHAR'
174
+ end
175
+ end
176
+
177
+ # read a node/edge def, and return a list where the first element is the
178
+ # label of the field, the second its type, and the third and last one its
179
+ # default value
180
+ # @param s
181
+ # @param defaults
182
+ def self.read_def(s, defaults={})
183
+ label, *params = s.split(/\s+/)
184
+ default = nil
185
+
186
+ if params.empty?
187
+ value_type = defaults[label.downcase] || 'VARCHAR'
188
+ else
189
+ value_type = params.shift
190
+
191
+ if params.shift == 'default'
192
+ default = parse_field(params.shift, value_type.downcase)
193
+ end
194
+
195
+ if /((tiny|small|medium|big)?int|integer)/i.match(value_type)
196
+ value_type = 'int'
197
+ elsif /(float|real|double)/i.match(value_type)
198
+ value_type = 'float'
199
+ elsif (value_type.downcase === 'boolean')
200
+ value_type = 'boolean'
201
+ end
202
+ end
203
+
204
+ [label, value_type, default]
205
+ end
206
+
207
+ # read a field and return its value
208
+ # @param f
209
+ # @param value_type [String]
210
+ # @param default
211
+ def self.parse_field(f, value_type, default=nil)
212
+ case value_type
213
+ when 'int' then (f || default).to_i
214
+ when 'float' then (f || default).to_f
215
+ when 'boolean' then
216
+ if f.nil?
217
+ default.nil? ? false : default
218
+ else
219
+ /^(?:null|false|)$/i !~ f
220
+ end
221
+ else f || default
222
+ end
223
+ end
224
+
225
+ end
@@ -0,0 +1,71 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ require 'json'
5
+ require_relative '../graph'
6
+
7
+ class Graph
8
+ # Returns a JSON version of the current graph
9
+ # @param opts [Hash] A customizable set of options
10
+ # @return [String]
11
+ # @see JSONGraph.unparse
12
+ def to_json(opts=nil)
13
+ JSONGraph::unparse(self, opts)
14
+ end
15
+
16
+ # Write the current graph into a JSON file. This method is used internally,
17
+ # use Graph#write instead.
18
+ # @param filename [String] a valid filename
19
+ # @return []
20
+ # @see JSON.unparse
21
+ def write_json(filename, opts=nil)
22
+ json = JSONGraph::unparse(self, opts)
23
+ f = File.open(filename, 'w')
24
+ f.write(json)
25
+ f.close
26
+ end
27
+ end
28
+
29
+ # JSON-related functions
30
+ module JSONGraph
31
+
32
+ # Loads a JSON file and return a new Graph object
33
+ # @param filename [String] a valid filename
34
+ # @return [Graph]
35
+ # @see JSONGraph.parse
36
+ def self.load(filename)
37
+ self.parse(File.read(filename))
38
+ end
39
+
40
+ # Parse some JSON text and return a new Graph object
41
+ # @param content [String] a valid GDF String
42
+ # @return [Graph]
43
+ # @see JSONGraph.load
44
+ # @see JSONGraph.unparse
45
+ def self.parse(content)
46
+
47
+ if (content.nil? || content.length == 0)
48
+ return Graph.new([],[])
49
+ end
50
+
51
+ content = JSON.parse content
52
+
53
+ nodes = content['nodes']
54
+ edges = content['edges']
55
+
56
+ Graph.new(nodes, edges)
57
+ end
58
+
59
+ # Return a JSON String which describe the given Graph
60
+ # @param graph [Graph]
61
+ # @param opts [Hash] A customizable set of options
62
+ # @return [String]
63
+ # @see Graph#write
64
+ def self.unparse(graph, opts=nil)
65
+
66
+ nodes = graph.nodes.map { |n| n.to_hash }
67
+ edges = graph.edges.map { |e| e.to_hash }
68
+
69
+ JSON.dump({ 'nodes' => nodes, 'edges' => edges })
70
+ end
71
+ end
@@ -0,0 +1,92 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ class Edge_test < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @@empty = Graph::Node.new
8
+ @@alice = Graph::Node.new('label' => 'Alice')
9
+
10
+ # Alice ----> Bob
11
+ # ↑ ↑
12
+ # | |
13
+ # Oscar -------'
14
+ @@sample_graph = Graph.new(
15
+ [
16
+ { 'label' => 'Alice' },
17
+ { 'label' => 'Bob' },
18
+ { 'label' => 'Oscar' }
19
+ ],
20
+ [
21
+ { 'node1' => 'Alice', 'node2' => 'Bob' },
22
+ { :node1 => 'Oscar', 'node2' => 'Alice'},
23
+ { 'node1' => 'Oscar', :node2 => 'Bob'}
24
+ ]
25
+ )
26
+
27
+ end
28
+
29
+ def test_edge_node1_attr
30
+ assert_equal('Alice', @@sample_graph.edges[0].node1)
31
+ assert_equal('Oscar', @@sample_graph.edges[1].node1)
32
+ end
33
+
34
+ def test_edge_node2_attr
35
+ assert_equal('Alice', @@sample_graph.edges[1].node2)
36
+ assert_equal('Bob', @@sample_graph.edges[2].node2)
37
+ end
38
+
39
+ def test_edge_update
40
+
41
+ e = Graph::Edge.new
42
+
43
+ assert_equal(true, e.update({}).is_a?(Graph::Edge))
44
+ end
45
+
46
+ def test_edge_init_with_another_edge
47
+
48
+ e = Graph::Edge.new({ :foo => 'bar' })
49
+
50
+ assert_equal( e, Graph::Edge.new(e) )
51
+
52
+ end
53
+
54
+ end
55
+
56
+ class EdgeArray_test < Test::Unit::TestCase
57
+
58
+ def test_edgearray_push_edge
59
+
60
+ e = Graph::Edge.new({ :foo => 42 })
61
+ ea = Graph::EdgeArray.new([])
62
+
63
+ ea.push(e)
64
+
65
+ assert_equal(e, ea[0])
66
+
67
+ end
68
+
69
+ def test_edgearray_push_hash
70
+
71
+ e = { :foo => 42 }
72
+ ea = Graph::EdgeArray.new([])
73
+
74
+ ea.push(e)
75
+
76
+ assert_equal(Graph::Edge.new(e), ea[0])
77
+
78
+ end
79
+
80
+ def test_edgearray_push_no_edge_nor_hash
81
+
82
+ ea = Graph::EdgeArray.new([])
83
+
84
+ assert_raise(TypeError) do
85
+
86
+ ea.push(42)
87
+
88
+ end
89
+
90
+ end
91
+
92
+ end
@@ -0,0 +1,377 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ module Utils
5
+ def self.get_sample_graph
6
+ @@sample_graph_1
7
+ end
8
+
9
+ @@sample_graph_1 = "nodedef>label VARCHAR,num INT,biglabel VARCHAR\n"
10
+ @@sample_graph_1 += "toto,14,TOTO\nlala,5,LALA\ntiti,988,TITI\n"
11
+ @@sample_graph_1 += "edgedef>node1 VARCHAR,node2 VARCHAR,directed BOOLEAN\n"
12
+ @@sample_graph_1 += "toto,lala,true\nlala,titi,true\n"
13
+ @@sample_graph_1 += "titi,lala,false\ntiti,toto,true\n"
14
+ end
15
+
16
+ class GDF_Graph_test < Test::Unit::TestCase
17
+
18
+ # == Graph#to_gdf == #
19
+
20
+ def test_empty_graph_to_gdf
21
+ g = Graph.new
22
+ empty_gdf = "nodedef>"
23
+
24
+ assert_equal(empty_gdf, g.to_gdf)
25
+ end
26
+
27
+ def test_sample_graph_to_gdf
28
+ gdf = Utils::get_sample_graph
29
+ g = GDF::parse(gdf)
30
+ assert_equal(gdf, g.to_gdf)
31
+ end
32
+
33
+ # == Graph#write('….gdf') == #
34
+
35
+ def test_empty_graph_write_gdf
36
+ g = Graph.new
37
+
38
+ f = Tempfile.new([ 'foo', '.gdf' ])
39
+ f.close
40
+
41
+ g.write(f.path)
42
+ g2 = GDF.load(f.path)
43
+
44
+ assert_equal(g, g2)
45
+ f.unlink
46
+ end
47
+ end
48
+
49
+ class GDF_test < Test::Unit::TestCase
50
+
51
+ # == GDF::parse == #
52
+
53
+ def test_parse_empty_graph
54
+ g = GDF::parse('')
55
+
56
+ assert_equal([], g.nodes)
57
+ assert_equal([], g.edges)
58
+ end
59
+
60
+ def test_parse_space_after_nodedef
61
+ g = GDF::parse("nodedef> foo VARCHAR\nbar")
62
+
63
+ assert_equal(1, g.nodes.length)
64
+ assert_equal('bar', g.nodes[0]['foo'])
65
+ end
66
+
67
+ def test_parse_quoted_value
68
+ code = <<EOC
69
+ nodedef>label VARCHAR
70
+ "foo"
71
+ EOC
72
+
73
+ g = GDF::parse(code)
74
+ assert_equal(1, g.nodes.length)
75
+ assert_equal('foo', g.nodes[0].attrs['label'])
76
+ end
77
+
78
+ def test_parse_quoted_value_with_quote
79
+ code = <<EOC
80
+ nodedef>label VARCHAR
81
+ "fo""o"
82
+ EOC
83
+
84
+ g = GDF::parse(code)
85
+ assert_equal(1, g.nodes.length)
86
+ assert_equal('fo"o', g.nodes[0].attrs['label'])
87
+ end
88
+
89
+ def test_parse_value_with_comma
90
+ code = <<EOC
91
+ nodedef>label VARCHAR,num INT
92
+ "foo,bar",42
93
+ EOC
94
+
95
+ g = GDF::parse(code)
96
+ assert_equal(1, g.nodes.length)
97
+ assert_equal('foo,bar', g.nodes[0].attrs['label'])
98
+ end
99
+
100
+ def test_parse_empty_graph_with_nodedef
101
+
102
+ s = "nodedef>label VARCHAR\n"
103
+
104
+ g = GDF::parse(s)
105
+
106
+ assert_equal([], g.nodes)
107
+ assert_equal([], g.edges)
108
+ end
109
+
110
+ def test_parse_empty_graph_with_nodedef_and_edgedef
111
+ s = "nodedef>label VARCHAR\nedgedef>node1 VARCHAR,node2 VARCHAR\n"
112
+ g = GDF::parse(s)
113
+
114
+ assert_equal([], g.nodes)
115
+ assert_equal([], g.edges)
116
+ end
117
+
118
+ def test_parse_one_node_no_edge_string_field
119
+ s = "nodedef>label VARCHAR\nfoo\n"
120
+ g = GDF::parse(s)
121
+
122
+ assert_equal(1, g.nodes.length)
123
+ assert_equal('foo', g.nodes[0]['label'])
124
+ assert_equal([], g.edges)
125
+ end
126
+
127
+ def test_parse_one_node_no_edge_tinyint_field
128
+ s = "nodedef>num TINYINT\n3\n"
129
+ g = GDF::parse(s)
130
+
131
+ assert_equal(1, g.nodes.length)
132
+ assert_equal(3, g.nodes[0]['num'])
133
+ assert_equal([], g.edges)
134
+ end
135
+
136
+ def test_parse_one_node_no_edge_smallint_field
137
+ s = "nodedef>num SMALLINT\n3\n"
138
+ g = GDF::parse(s)
139
+
140
+ assert_equal(1, g.nodes.length)
141
+ assert_equal(3, g.nodes[0]['num'])
142
+ assert_equal([], g.edges)
143
+ end
144
+
145
+ def test_parse_one_node_no_edge_int_field
146
+ s = "nodedef>num INT\n3\n"
147
+ g = GDF::parse(s)
148
+
149
+ assert_equal(1, g.nodes.length)
150
+ assert_equal(3, g.nodes[0]['num'])
151
+ assert_equal([], g.edges)
152
+ end
153
+
154
+ def test_parse_one_node_no_edge_negative_int_field
155
+ s = "nodedef>num INT\n-1337\n"
156
+ g = GDF::parse(s)
157
+
158
+ assert_equal(1, g.nodes.length)
159
+ assert_equal(-1337, g.nodes[0]['num'])
160
+ assert_equal([], g.edges)
161
+ end
162
+
163
+ def test_parse_one_node_no_edge_bigint_field
164
+ s = "nodedef>num BIGINT\n3\n"
165
+ g = GDF::parse(s)
166
+
167
+ assert_equal(1, g.nodes.length)
168
+ assert_equal(3, g.nodes[0]['num'])
169
+ assert_equal([], g.edges)
170
+ end
171
+
172
+ def test_parse_one_node_no_edge_float_field
173
+ s = "nodedef>num FLOAT\n3\n"
174
+ g = GDF::parse(s)
175
+
176
+ assert_equal(1, g.nodes.length)
177
+ assert_equal(3.0, g.nodes[0]['num'])
178
+ assert_equal([], g.edges)
179
+ end
180
+
181
+ def test_parse_one_node_no_edge_double_field
182
+ s = "nodedef>num FLOAT\n3\n"
183
+ g = GDF::parse(s)
184
+
185
+ assert_equal(1, g.nodes.length)
186
+ assert_equal(3.0, g.nodes[0]['num'])
187
+ assert_equal([], g.edges)
188
+ end
189
+
190
+ def test_parse_one_node_no_edge_real_field
191
+ s = "nodedef>num FLOAT\n3\n"
192
+ g = GDF::parse(s)
193
+
194
+ assert_equal(1, g.nodes.length)
195
+ assert_equal(3.0, g.nodes[0]['num'])
196
+ assert_equal([], g.edges)
197
+ end
198
+
199
+ def test_parse_one_node_no_edge_negative_real_field
200
+ s = "nodedef>num FLOAT\n-42.14\n"
201
+ g = GDF::parse(s)
202
+
203
+ assert_equal(1, g.nodes.length)
204
+ assert_equal(-42.14, g.nodes[0]['num'])
205
+ assert_equal([], g.edges)
206
+ end
207
+
208
+ def test_parse_one_node_no_edge_unknow_field_type
209
+ s = "nodedef>foo BAR\nfoobar"
210
+ g = GDF::parse(s)
211
+
212
+ assert_equal(1, g.nodes.length)
213
+ assert_equal('foobar', g.nodes[0]['foo'])
214
+ assert_equal([], g.edges)
215
+ end
216
+
217
+ def test_parse_one_node_no_type
218
+ s = "nodedef>foo\nfoobar"
219
+ g = GDF::parse(s)
220
+
221
+ assert_equal(1, g.nodes.length)
222
+ assert_equal('foobar', g.nodes[0]['foo'])
223
+ assert_equal([], g.edges)
224
+ end
225
+
226
+ def test_parse_one_node_builtin_visible_prop_no_type
227
+ s = "nodedef>visible,foo VARCHAR\n,bar\n"
228
+ g = GDF::parse(s)
229
+
230
+ assert_equal(1, g.nodes.length)
231
+ assert_equal('bar', g.nodes[0]['foo'])
232
+ assert_equal(false, g.nodes[0]['visible'])
233
+ end
234
+
235
+ def test_parse_one_node_builtin_visible_prop_with_type
236
+ s = "nodedef>visible BOOLEAN,foo VARCHAR\n,bar\n"
237
+ g = GDF::parse(s)
238
+
239
+ assert_equal(1, g.nodes.length)
240
+ assert_equal('bar', g.nodes[0]['foo'])
241
+ assert_equal(false, g.nodes[0]['visible'])
242
+ end
243
+
244
+ def test_parse_one_node_truthy_boolean_value
245
+ s = "nodedef>xyz BOOLEAN,foo VARCHAR\nxfalse,bar\n"
246
+ g = GDF::parse(s)
247
+
248
+ assert_equal(1, g.nodes.length)
249
+ assert_equal('bar', g.nodes[0]['foo'])
250
+ assert_equal(true, g.nodes[0]['xyz'])
251
+ end
252
+
253
+ def test_parse_one_node_null_boolean_value
254
+ s = "nodedef>xyz BOOLEAN,foo VARCHAR\nnull,bar\n"
255
+ g = GDF::parse(s)
256
+
257
+ assert_equal(1, g.nodes.length)
258
+ assert_equal('bar', g.nodes[0]['foo'])
259
+ assert_equal(false, g.nodes[0]['xyz'])
260
+ end
261
+
262
+ def test_parse_nodes_only_one_empty_boolean_value
263
+ s = "nodedef>xyz BOOLEAN\n\n\n"
264
+ g = GDF::parse(s)
265
+
266
+ assert_equal(2, g.nodes.length)
267
+ assert_equal(false, g.nodes[0]['xyz'])
268
+ assert_equal(false, g.nodes[1]['xyz'])
269
+ end
270
+
271
+ def test_parse_nodes_default_int_value
272
+ s = "nodedef>xyz INT default 42,foo VARCHAR\n,bar\n12,foo"
273
+ g = GDF::parse(s)
274
+
275
+ assert_equal(2, g.nodes.length)
276
+ assert_equal(42, g.nodes[0]['xyz'])
277
+ assert_equal(12, g.nodes[1]['xyz'])
278
+ end
279
+
280
+ def test_parse_nodes_default_boolean_value_true
281
+ s = "nodedef>xyz BOOLEAN default true,foo VARCHAR\n,bar\nfalse,foo"
282
+ g = GDF::parse(s)
283
+
284
+ assert_equal(2, g.nodes.length)
285
+ assert_equal(true, g.nodes[0]['xyz'])
286
+ assert_equal(false, g.nodes[1]['xyz'])
287
+ end
288
+
289
+ def test_parse_nodes_default_boolean_value_false
290
+ s = "nodedef>xyz BOOLEAN default false,foo VARCHAR\n,bar\ntrue,foo"
291
+ g = GDF::parse(s)
292
+
293
+ assert_equal(2, g.nodes.length)
294
+ assert_equal(false, g.nodes[0]['xyz'])
295
+ assert_equal(true, g.nodes[1]['xyz'])
296
+ end
297
+
298
+ def test_parse_one_edge_no_type
299
+ s = "nodedef>label VARCHAR\nfoobar\nedgedef>node1,node2\nfoobar,foobar"
300
+ g = GDF::parse(s)
301
+
302
+ assert_equal(1, g.nodes.length)
303
+ assert_equal('foobar', g.nodes[0]['label'])
304
+ assert_equal('foobar', g.edges[0]['node1'])
305
+ assert_equal('foobar', g.edges[0]['node2'])
306
+ end
307
+
308
+ def test_parse_sample_graph
309
+ g = GDF::parse(Utils::get_sample_graph)
310
+
311
+ assert_equal(3, g.nodes.length)
312
+ assert_equal(4, g.edges.length)
313
+
314
+ assert_equal('toto', g.nodes[0]['label'])
315
+ assert_equal('TOTO', g.nodes[0]['biglabel'])
316
+ assert_equal(988, g.nodes[2]['num'])
317
+
318
+ assert_equal('toto', g.edges[0]['node1'])
319
+ assert_equal('lala', g.edges[0]['node2'])
320
+ assert_equal(false, g.edges[2]['directed'])
321
+
322
+ end
323
+
324
+ # == GDF::unparse == #
325
+
326
+ def test_unparse_empty_graph
327
+ g = Graph.new
328
+
329
+ s = GDF::unparse(g)
330
+
331
+ assert_equal("nodedef>", s)
332
+ end
333
+
334
+ def test_unparse_sample_graph
335
+ g1 = GDF::parse(Utils::get_sample_graph)
336
+ g2 = GDF::parse(GDF::unparse(g1))
337
+
338
+ assert_equal(g1, g2)
339
+ end
340
+
341
+ def test_unparse_big_int
342
+ n = 2**40
343
+ g = Graph.new([{'n'=>n}])
344
+ gdf = GDF::unparse(g)
345
+
346
+ assert_equal("nodedef>n BIGINT\n#{n}\nedgedef>", gdf)
347
+ end
348
+
349
+ def test_unparse_big_int_gephi
350
+ n = 2**40
351
+ g = Graph.new([{'n'=>n}])
352
+ gdf = GDF::unparse(g, {:gephi=>true})
353
+
354
+ assert_equal("nodedef>n INT\n#{n}\nedgedef>", gdf)
355
+ end
356
+
357
+ def test_unparse_float_field
358
+ g = Graph.new([{ 'n' => 3.14 }])
359
+ gdf = GDF::unparse(g)
360
+
361
+ assert_equal("nodedef>n FLOAT\n3.14\nedgedef>", gdf)
362
+ end
363
+
364
+ def test_unparse_value_with_quote
365
+ g = Graph.new([{'n' => 'foo"bar'}])
366
+ gdf = GDF::unparse(g)
367
+
368
+ assert_equal("nodedef>n VARCHAR\n\"foo\"\"bar\"\nedgedef>", gdf)
369
+ end
370
+
371
+ def test_unparse_value_with_comma
372
+ g = Graph.new([{'n' => 'foo,bar'}])
373
+ gdf = GDF::unparse(g)
374
+
375
+ assert_equal("nodedef>n VARCHAR\n\"foo,bar\"\nedgedef>", gdf)
376
+ end
377
+ end