blob: dde9f43f494f989df74bcca104eeb7a47b485f08 [file] [log] [blame]
// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gexf12
import (
"encoding/xml"
"io/ioutil"
"path/filepath"
"reflect"
"testing"
"time"
)
var gexfExampleTests = []struct {
path string
unmarshaled Content
marshaled string
}{
{
path: "basic.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Meta: nil,
Graph: Graph{
Attributes: nil,
Nodes: Nodes{
Nodes: []Node{
{ID: "0", Label: "Hello"},
{ID: "1", Label: "Word"},
},
},
Edges: Edges{
Edges: []Edge{
{ID: "0", Source: "0", Target: "1"},
},
},
DefaultEdgeType: "directed",
Mode: "static",
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<graph defaultedgetype="directed" mode="static">
<nodes>
<node id="0" label="Hello"></node>
<node id="1" label="Word"></node>
</nodes>
<edges>
<edge id="0" source="0" target="1"></edge>
</edges>
</graph>
</gexf>`,
},
{
path: "data.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Meta: &Meta{
Creator: "Gephi.org",
Description: "A Web network",
LastModified: time.Date(2009, 03, 20, 0, 0, 0, 0, time.UTC),
},
Graph: Graph{
Attributes: []Attributes{{
Class: "node",
Attributes: []Attribute{
{
ID: "0",
Title: "url",
Type: "string",
},
{
ID: "1",
Title: "indegree",
Type: "float",
},
{
ID: "2",
Title: "frog",
Type: "boolean",
Default: "true",
},
},
}},
Nodes: Nodes{
Nodes: []Node{
{
ID: "0", Label: "Gephi",
AttValues: &AttValues{AttValues: []AttValue{
{For: "0", Value: "http://gephi.org"},
{For: "1", Value: "1"},
}},
},
{
ID: "1", Label: "Webatlas",
AttValues: &AttValues{AttValues: []AttValue{
{For: "0", Value: "http://webatlas.fr"},
{For: "1", Value: "2"},
}},
},
{
ID: "2", Label: "RTGI",
AttValues: &AttValues{AttValues: []AttValue{
{For: "0", Value: "http://rtgi.fr"},
{For: "1", Value: "1"},
}},
},
{
ID: "3", Label: "BarabasiLab",
AttValues: &AttValues{AttValues: []AttValue{
{For: "0", Value: "http://barabasilab.com"},
{For: "1", Value: "1"},
{For: "2", Value: "false"},
}},
},
},
},
Edges: Edges{
Edges: []Edge{
{ID: "0", Source: "0", Target: "1"},
{ID: "1", Source: "0", Target: "2"},
{ID: "2", Source: "1", Target: "0"},
{ID: "3", Source: "2", Target: "1"},
{ID: "4", Source: "0", Target: "3"},
},
},
DefaultEdgeType: "directed",
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<meta lastmodifieddate="2009-03-20">
<creator>Gephi.org</creator>
<description>A Web network</description>
</meta>
<graph defaultedgetype="directed">
<attributes class="node">
<attribute id="0" title="url" type="string"></attribute>
<attribute id="1" title="indegree" type="float"></attribute>
<attribute id="2" title="frog" type="boolean">
<default>true</default>
</attribute>
</attributes>
<nodes>
<node id="0" label="Gephi">
<attvalues>
<attvalue for="0" value="http://gephi.org"></attvalue>
<attvalue for="1" value="1"></attvalue>
</attvalues>
</node>
<node id="1" label="Webatlas">
<attvalues>
<attvalue for="0" value="http://webatlas.fr"></attvalue>
<attvalue for="1" value="2"></attvalue>
</attvalues>
</node>
<node id="2" label="RTGI">
<attvalues>
<attvalue for="0" value="http://rtgi.fr"></attvalue>
<attvalue for="1" value="1"></attvalue>
</attvalues>
</node>
<node id="3" label="BarabasiLab">
<attvalues>
<attvalue for="0" value="http://barabasilab.com"></attvalue>
<attvalue for="1" value="1"></attvalue>
<attvalue for="2" value="false"></attvalue>
</attvalues>
</node>
</nodes>
<edges>
<edge id="0" source="0" target="1"></edge>
<edge id="1" source="0" target="2"></edge>
<edge id="2" source="1" target="0"></edge>
<edge id="3" source="2" target="1"></edge>
<edge id="4" source="0" target="3"></edge>
</edges>
</graph>
</gexf>`,
},
{
path: "hierarchy1.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Meta: &Meta{
Creator: "Gephi.org",
Description: "A hierarchy file",
LastModified: time.Date(2009, 10, 1, 0, 0, 0, 0, time.UTC),
},
Graph: Graph{
Nodes: Nodes{
Nodes: []Node{{
ID: "a",
Label: "Kevin Bacon",
Nodes: &Nodes{
Nodes: []Node{
{
ID: "b", Label: "God",
Nodes: &Nodes{
Nodes: []Node{
{ID: "c", Label: "human1"},
{ID: "d", Label: "human2"},
{ID: "i", Label: "human3"},
},
},
},
{
ID: "e", Label: "Me",
Nodes: &Nodes{
Nodes: []Node{
{ID: "f", Label: "frog1"},
{ID: "g", Label: "frog2"},
{ID: "h", Label: "frog3"},
},
},
},
{
ID: "j", Label: "You",
},
},
},
}},
},
Edges: Edges{
Edges: []Edge{
{ID: "0", Source: "b", Target: "e"},
{ID: "1", Source: "c", Target: "d"},
{ID: "2", Source: "c", Target: "i"},
{ID: "3", Source: "g", Target: "b"},
{ID: "4", Source: "f", Target: "a"},
{ID: "5", Source: "f", Target: "g"},
{ID: "6", Source: "f", Target: "h"},
{ID: "7", Source: "g", Target: "h"},
{ID: "8", Source: "a", Target: "j"},
},
},
DefaultEdgeType: "directed",
Mode: "static",
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<meta lastmodifieddate="2009-10-01">
<creator>Gephi.org</creator>
<description>A hierarchy file</description>
</meta>
<graph defaultedgetype="directed" mode="static">
<nodes>
<node id="a" label="Kevin Bacon">
<nodes>
<node id="b" label="God">
<nodes>
<node id="c" label="human1"></node>
<node id="d" label="human2"></node>
<node id="i" label="human3"></node>
</nodes>
</node>
<node id="e" label="Me">
<nodes>
<node id="f" label="frog1"></node>
<node id="g" label="frog2"></node>
<node id="h" label="frog3"></node>
</nodes>
</node>
<node id="j" label="You"></node>
</nodes>
</node>
</nodes>
<edges>
<edge id="0" source="b" target="e"></edge>
<edge id="1" source="c" target="d"></edge>
<edge id="2" source="c" target="i"></edge>
<edge id="3" source="g" target="b"></edge>
<edge id="4" source="f" target="a"></edge>
<edge id="5" source="f" target="g"></edge>
<edge id="6" source="f" target="h"></edge>
<edge id="7" source="g" target="h"></edge>
<edge id="8" source="a" target="j"></edge>
</edges>
</graph>
</gexf>`,
},
{
path: "hierarchy4.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Meta: &Meta{
Creator: "Gephi.org",
Keywords: "",
Description: "A hierarchy file",
LastModified: time.Date(2009, 10, 1, 0, 0, 0, 0, time.UTC),
},
Graph: Graph{
Nodes: Nodes{
Nodes: []Node{
{ID: "g", Label: "frog2", ParentID: "e"},
{ID: "a", Label: "Kevin Bacon"},
{ID: "c", Label: "human1", ParentID: "b"},
{ID: "b", Label: "God", ParentID: "a"},
{ID: "e", Label: "Me", ParentID: "a"},
{ID: "d", Label: "human2", ParentID: "b"},
{ID: "f", Label: "frog1", ParentID: "e"},
},
},
Edges: Edges{
Edges: []Edge{
{ID: "0", Source: "b", Target: "e"},
{ID: "1", Source: "c", Target: "d"},
{ID: "2", Source: "g", Target: "b"},
{ID: "3", Source: "f", Target: "a"},
},
},
DefaultEdgeType: "directed",
Mode: "static",
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<meta lastmodifieddate="2009-10-01">
<creator>Gephi.org</creator>
<description>A hierarchy file</description>
</meta>
<graph defaultedgetype="directed" mode="static">
<nodes>
<node id="g" label="frog2" pid="e"></node>
<node id="a" label="Kevin Bacon"></node>
<node id="c" label="human1" pid="b"></node>
<node id="b" label="God" pid="a"></node>
<node id="e" label="Me" pid="a"></node>
<node id="d" label="human2" pid="b"></node>
<node id="f" label="frog1" pid="e"></node>
</nodes>
<edges>
<edge id="0" source="b" target="e"></edge>
<edge id="1" source="c" target="d"></edge>
<edge id="2" source="g" target="b"></edge>
<edge id="3" source="f" target="a"></edge>
</edges>
</graph>
</gexf>`,
},
{
path: "phylogeny.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Graph: Graph{
Nodes: Nodes{
Nodes: []Node{
{ID: "a", Label: "cheese"},
{ID: "b", Label: "cherry"},
{ID: "c", Label: "cake", Parents: &Parents{
Parents: []Parent{
{For: "a"},
{For: "b"},
},
},
},
},
},
Edges: Edges{
Edges: nil,
Count: 0,
},
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<graph>
<nodes>
<node id="a" label="cheese"></node>
<node id="b" label="cherry"></node>
<node id="c" label="cake">
<parents>
<parent for="a"></parent>
<parent for="b"></parent>
</parents>
</node>
</nodes>
<edges></edges>
</graph>
</gexf>`,
},
{
path: "viz.gexf",
unmarshaled: Content{
XMLName: xml.Name{Space: "http://www.gexf.net/1.2draft", Local: "gexf"},
Graph: Graph{
Nodes: Nodes{
Nodes: []Node{
{
ID: "a",
Label: "glossy",
Color: &Color{
R: 239,
G: 173,
B: 66,
A: 0.6,
},
Position: &Position{
X: 15.783598,
Y: 40.109245,
Z: 0,
},
Size: &Size{
Value: 2.0375757,
},
},
},
},
Edges: Edges{},
},
Version: "1.2",
},
marshaled: `<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<graph>
<nodes>
<node id="a" label="glossy">
<color xmlns="http://www.gexf.net/1.2draft/viz" r="239" g="173" b="66" a="0.6"></color>
<position xmlns="http://www.gexf.net/1.2draft/viz" x="15.783598" y="40.109245" z="0"></position>
<size xmlns="http://www.gexf.net/1.2draft/viz" value="2.0375757"></size>
</node>
</nodes>
<edges></edges>
</graph>
</gexf>`,
},
}
func TestUnmarshal(t *testing.T) {
for _, test := range gexfExampleTests {
data, err := ioutil.ReadFile(filepath.Join("testdata", test.path))
if err != nil {
t.Errorf("failed to read %q: %v", test.path, err)
continue
}
var got Content
err = xml.Unmarshal(data, &got)
if !reflect.DeepEqual(got, test.unmarshaled) {
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got, test.unmarshaled)
}
}
}
// TODO(kortschak): Update this test when/if namespace
// prefix handling in encoding/xml is fixed.
func TestMarshal(t *testing.T) {
for _, test := range gexfExampleTests {
got, err := xml.MarshalIndent(test.unmarshaled, "", "\t")
if err != nil {
t.Errorf("failed to marshal %q: %v", test.path, err)
continue
}
if string(got) != test.marshaled {
t.Errorf("unexpected result for %q:\ngot:\n%s\nwant:\n%s", test.path, got, test.marshaled)
}
}
}