github.com/gopherd/gonum@v0.0.4/graph/formats/gexf12/gexf_test.go (about) 1 // Copyright ©2018 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gexf12 6 7 import ( 8 "encoding/xml" 9 "os" 10 "path/filepath" 11 "reflect" 12 "testing" 13 "time" 14 ) 15 16 var gexfExampleTests = []struct { 17 path string 18 unmarshaled Content 19 marshaled string 20 }{ 21 { 22 path: "basic.gexf", 23 unmarshaled: Content{ 24 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 25 Meta: nil, 26 Graph: Graph{ 27 Attributes: nil, 28 Nodes: Nodes{ 29 Nodes: []Node{ 30 {ID: "0", Label: "Hello"}, 31 {ID: "1", Label: "Word"}, 32 }, 33 }, 34 Edges: Edges{ 35 Edges: []Edge{ 36 {ID: "0", Source: "0", Target: "1"}, 37 }, 38 }, 39 DefaultEdgeType: "directed", 40 Mode: "static", 41 }, 42 Version: "1.2", 43 }, 44 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 45 <graph defaultedgetype="directed" mode="static"> 46 <nodes> 47 <node id="0" label="Hello"></node> 48 <node id="1" label="Word"></node> 49 </nodes> 50 <edges> 51 <edge id="0" source="0" target="1"></edge> 52 </edges> 53 </graph> 54 </gexf>`, 55 }, 56 { 57 path: "data.gexf", 58 unmarshaled: Content{ 59 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 60 Meta: &Meta{ 61 Creator: "Gephi.org", 62 Description: "A Web network", 63 LastModified: time.Date(2009, 03, 20, 0, 0, 0, 0, time.UTC), 64 }, 65 Graph: Graph{ 66 Attributes: []Attributes{{ 67 Class: "node", 68 Attributes: []Attribute{ 69 { 70 ID: "0", 71 Title: "url", 72 Type: "string", 73 }, 74 { 75 ID: "1", 76 Title: "indegree", 77 Type: "float", 78 }, 79 { 80 ID: "2", 81 Title: "frog", 82 Type: "boolean", 83 Default: "true", 84 }, 85 }, 86 }}, 87 Nodes: Nodes{ 88 Nodes: []Node{ 89 { 90 ID: "0", Label: "Gephi", 91 AttValues: &AttValues{AttValues: []AttValue{ 92 {For: "0", Value: "http://gephi.org"}, 93 {For: "1", Value: "1"}, 94 }}, 95 }, 96 { 97 ID: "1", Label: "Webatlas", 98 AttValues: &AttValues{AttValues: []AttValue{ 99 {For: "0", Value: "http://webatlas.fr"}, 100 {For: "1", Value: "2"}, 101 }}, 102 }, 103 { 104 ID: "2", Label: "RTGI", 105 AttValues: &AttValues{AttValues: []AttValue{ 106 {For: "0", Value: "http://rtgi.fr"}, 107 {For: "1", Value: "1"}, 108 }}, 109 }, 110 { 111 ID: "3", Label: "BarabasiLab", 112 AttValues: &AttValues{AttValues: []AttValue{ 113 {For: "0", Value: "http://barabasilab.com"}, 114 {For: "1", Value: "1"}, 115 {For: "2", Value: "false"}, 116 }}, 117 }, 118 }, 119 }, 120 Edges: Edges{ 121 Edges: []Edge{ 122 {ID: "0", Source: "0", Target: "1"}, 123 {ID: "1", Source: "0", Target: "2"}, 124 {ID: "2", Source: "1", Target: "0"}, 125 {ID: "3", Source: "2", Target: "1"}, 126 {ID: "4", Source: "0", Target: "3"}, 127 }, 128 }, 129 DefaultEdgeType: "directed", 130 }, 131 Version: "1.2", 132 }, 133 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 134 <meta lastmodifieddate="2009-03-20"> 135 <creator>Gephi.org</creator> 136 <description>A Web network</description> 137 </meta> 138 <graph defaultedgetype="directed"> 139 <attributes class="node"> 140 <attribute id="0" title="url" type="string"></attribute> 141 <attribute id="1" title="indegree" type="float"></attribute> 142 <attribute id="2" title="frog" type="boolean"> 143 <default>true</default> 144 </attribute> 145 </attributes> 146 <nodes> 147 <node id="0" label="Gephi"> 148 <attvalues> 149 <attvalue for="0" value="http://gephi.org"></attvalue> 150 <attvalue for="1" value="1"></attvalue> 151 </attvalues> 152 </node> 153 <node id="1" label="Webatlas"> 154 <attvalues> 155 <attvalue for="0" value="http://webatlas.fr"></attvalue> 156 <attvalue for="1" value="2"></attvalue> 157 </attvalues> 158 </node> 159 <node id="2" label="RTGI"> 160 <attvalues> 161 <attvalue for="0" value="http://rtgi.fr"></attvalue> 162 <attvalue for="1" value="1"></attvalue> 163 </attvalues> 164 </node> 165 <node id="3" label="BarabasiLab"> 166 <attvalues> 167 <attvalue for="0" value="http://barabasilab.com"></attvalue> 168 <attvalue for="1" value="1"></attvalue> 169 <attvalue for="2" value="false"></attvalue> 170 </attvalues> 171 </node> 172 </nodes> 173 <edges> 174 <edge id="0" source="0" target="1"></edge> 175 <edge id="1" source="0" target="2"></edge> 176 <edge id="2" source="1" target="0"></edge> 177 <edge id="3" source="2" target="1"></edge> 178 <edge id="4" source="0" target="3"></edge> 179 </edges> 180 </graph> 181 </gexf>`, 182 }, 183 { 184 path: "hierarchy1.gexf", 185 unmarshaled: Content{ 186 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 187 Meta: &Meta{ 188 Creator: "Gephi.org", 189 Description: "A hierarchy file", 190 LastModified: time.Date(2009, 10, 1, 0, 0, 0, 0, time.UTC), 191 }, 192 Graph: Graph{ 193 Nodes: Nodes{ 194 Nodes: []Node{{ 195 ID: "a", 196 Label: "Kevin Bacon", 197 Nodes: &Nodes{ 198 Nodes: []Node{ 199 { 200 ID: "b", Label: "God", 201 Nodes: &Nodes{ 202 Nodes: []Node{ 203 {ID: "c", Label: "human1"}, 204 {ID: "d", Label: "human2"}, 205 {ID: "i", Label: "human3"}, 206 }, 207 }, 208 }, 209 { 210 ID: "e", Label: "Me", 211 Nodes: &Nodes{ 212 Nodes: []Node{ 213 {ID: "f", Label: "frog1"}, 214 {ID: "g", Label: "frog2"}, 215 {ID: "h", Label: "frog3"}, 216 }, 217 }, 218 }, 219 { 220 ID: "j", Label: "You", 221 }, 222 }, 223 }, 224 }}, 225 }, 226 Edges: Edges{ 227 Edges: []Edge{ 228 {ID: "0", Source: "b", Target: "e"}, 229 {ID: "1", Source: "c", Target: "d"}, 230 {ID: "2", Source: "c", Target: "i"}, 231 {ID: "3", Source: "g", Target: "b"}, 232 {ID: "4", Source: "f", Target: "a"}, 233 {ID: "5", Source: "f", Target: "g"}, 234 {ID: "6", Source: "f", Target: "h"}, 235 {ID: "7", Source: "g", Target: "h"}, 236 {ID: "8", Source: "a", Target: "j"}, 237 }, 238 }, 239 DefaultEdgeType: "directed", 240 Mode: "static", 241 }, 242 Version: "1.2", 243 }, 244 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 245 <meta lastmodifieddate="2009-10-01"> 246 <creator>Gephi.org</creator> 247 <description>A hierarchy file</description> 248 </meta> 249 <graph defaultedgetype="directed" mode="static"> 250 <nodes> 251 <node id="a" label="Kevin Bacon"> 252 <nodes> 253 <node id="b" label="God"> 254 <nodes> 255 <node id="c" label="human1"></node> 256 <node id="d" label="human2"></node> 257 <node id="i" label="human3"></node> 258 </nodes> 259 </node> 260 <node id="e" label="Me"> 261 <nodes> 262 <node id="f" label="frog1"></node> 263 <node id="g" label="frog2"></node> 264 <node id="h" label="frog3"></node> 265 </nodes> 266 </node> 267 <node id="j" label="You"></node> 268 </nodes> 269 </node> 270 </nodes> 271 <edges> 272 <edge id="0" source="b" target="e"></edge> 273 <edge id="1" source="c" target="d"></edge> 274 <edge id="2" source="c" target="i"></edge> 275 <edge id="3" source="g" target="b"></edge> 276 <edge id="4" source="f" target="a"></edge> 277 <edge id="5" source="f" target="g"></edge> 278 <edge id="6" source="f" target="h"></edge> 279 <edge id="7" source="g" target="h"></edge> 280 <edge id="8" source="a" target="j"></edge> 281 </edges> 282 </graph> 283 </gexf>`, 284 }, 285 { 286 path: "hierarchy4.gexf", 287 unmarshaled: Content{ 288 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 289 Meta: &Meta{ 290 Creator: "Gephi.org", 291 Keywords: "", 292 Description: "A hierarchy file", 293 LastModified: time.Date(2009, 10, 1, 0, 0, 0, 0, time.UTC), 294 }, 295 Graph: Graph{ 296 Nodes: Nodes{ 297 Nodes: []Node{ 298 {ID: "g", Label: "frog2", ParentID: "e"}, 299 {ID: "a", Label: "Kevin Bacon"}, 300 {ID: "c", Label: "human1", ParentID: "b"}, 301 {ID: "b", Label: "God", ParentID: "a"}, 302 {ID: "e", Label: "Me", ParentID: "a"}, 303 {ID: "d", Label: "human2", ParentID: "b"}, 304 {ID: "f", Label: "frog1", ParentID: "e"}, 305 }, 306 }, 307 Edges: Edges{ 308 Edges: []Edge{ 309 {ID: "0", Source: "b", Target: "e"}, 310 {ID: "1", Source: "c", Target: "d"}, 311 {ID: "2", Source: "g", Target: "b"}, 312 {ID: "3", Source: "f", Target: "a"}, 313 }, 314 }, 315 DefaultEdgeType: "directed", 316 Mode: "static", 317 }, 318 Version: "1.2", 319 }, 320 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 321 <meta lastmodifieddate="2009-10-01"> 322 <creator>Gephi.org</creator> 323 <description>A hierarchy file</description> 324 </meta> 325 <graph defaultedgetype="directed" mode="static"> 326 <nodes> 327 <node id="g" label="frog2" pid="e"></node> 328 <node id="a" label="Kevin Bacon"></node> 329 <node id="c" label="human1" pid="b"></node> 330 <node id="b" label="God" pid="a"></node> 331 <node id="e" label="Me" pid="a"></node> 332 <node id="d" label="human2" pid="b"></node> 333 <node id="f" label="frog1" pid="e"></node> 334 </nodes> 335 <edges> 336 <edge id="0" source="b" target="e"></edge> 337 <edge id="1" source="c" target="d"></edge> 338 <edge id="2" source="g" target="b"></edge> 339 <edge id="3" source="f" target="a"></edge> 340 </edges> 341 </graph> 342 </gexf>`, 343 }, 344 { 345 path: "phylogeny.gexf", 346 unmarshaled: Content{ 347 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 348 Graph: Graph{ 349 Nodes: Nodes{ 350 Nodes: []Node{ 351 {ID: "a", Label: "cheese"}, 352 {ID: "b", Label: "cherry"}, 353 {ID: "c", Label: "cake", Parents: &Parents{ 354 Parents: []Parent{ 355 {For: "a"}, 356 {For: "b"}, 357 }, 358 }, 359 }, 360 }, 361 }, 362 Edges: Edges{ 363 Edges: nil, 364 Count: 0, 365 }, 366 }, 367 Version: "1.2", 368 }, 369 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 370 <graph> 371 <nodes> 372 <node id="a" label="cheese"></node> 373 <node id="b" label="cherry"></node> 374 <node id="c" label="cake"> 375 <parents> 376 <parent for="a"></parent> 377 <parent for="b"></parent> 378 </parents> 379 </node> 380 </nodes> 381 <edges></edges> 382 </graph> 383 </gexf>`, 384 }, 385 { 386 path: "viz.gexf", 387 unmarshaled: Content{ 388 XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"}, 389 Graph: Graph{ 390 Nodes: Nodes{ 391 Nodes: []Node{ 392 { 393 ID: "a", 394 Label: "glossy", 395 Color: &Color{ 396 R: 239, 397 G: 173, 398 B: 66, 399 A: 0.6, 400 }, 401 Position: &Position{ 402 X: 15.783598, 403 Y: 40.109245, 404 Z: 0, 405 }, 406 Size: &Size{ 407 Value: 2.0375757, 408 }, 409 }, 410 }, 411 }, 412 Edges: Edges{}, 413 }, 414 Version: "1.2", 415 }, 416 marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2"> 417 <graph> 418 <nodes> 419 <node id="a" label="glossy"> 420 <color xmlns="http://www.gexf.net/1.2draft/viz" r="239" g="173" b="66" a="0.6"></color> 421 <position xmlns="http://www.gexf.net/1.2draft/viz" x="15.783598" y="40.109245" z="0"></position> 422 <size xmlns="http://www.gexf.net/1.2draft/viz" value="2.0375757"></size> 423 </node> 424 </nodes> 425 <edges></edges> 426 </graph> 427 </gexf>`, 428 }, 429 } 430 431 func TestUnmarshal(t *testing.T) { 432 for _, test := range gexfExampleTests { 433 data, err := os.ReadFile(filepath.Join("testdata", test.path)) 434 if err != nil { 435 t.Errorf("failed to read %q: %v", test.path, err) 436 continue 437 } 438 var got Content 439 err = xml.Unmarshal(data, &got) 440 if err != nil { 441 t.Errorf("failed to unmarshal %q: %v", test.path, err) 442 } 443 if !reflect.DeepEqual(got, test.unmarshaled) { 444 t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got, test.unmarshaled) 445 } 446 } 447 } 448 449 // TODO(kortschak): Update this test when/if namespace 450 // prefix handling in encoding/xml is fixed. 451 func TestMarshal(t *testing.T) { 452 for _, test := range gexfExampleTests { 453 got, err := xml.MarshalIndent(test.unmarshaled, "", "\t") 454 if err != nil { 455 t.Errorf("failed to marshal %q: %v", test.path, err) 456 continue 457 } 458 if string(got) != test.marshaled { 459 t.Errorf("unexpected result for %q:\ngot:\n%s\nwant:\n%s", test.path, got, test.marshaled) 460 } 461 } 462 }