// 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" "os" "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: ` `, }, { 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: ` Gephi.org A Web network true `, }, { 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: ` Gephi.org A hierarchy file `, }, { 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: ` Gephi.org A hierarchy file `, }, { 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: ` `, }, { 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: ` `, }, } func TestUnmarshal(t *testing.T) { for _, test := range gexfExampleTests { data, err := os.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 err != nil { t.Errorf("failed to unmarshal %q: %v", test.path, err) } 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) } } }