gonum.org/v1/gonum@v0.14.0/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  }