mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 23:26:52 +08:00
372 lines
11 KiB
Go
372 lines
11 KiB
Go
// 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 cytoscapejs
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
var cytoscapejsElementsTests = []struct {
|
|
path string
|
|
wantNodes int
|
|
wantEdges int
|
|
wantGraph []Element
|
|
wantAttributes []string
|
|
}{
|
|
{
|
|
path: "edge-type.json",
|
|
wantNodes: 10,
|
|
wantEdges: 10,
|
|
wantGraph: []Element{
|
|
{Data: ElemData{ID: "n01", Attributes: map[string]interface{}{"type": "bezier"}}},
|
|
{Data: ElemData{ID: "n02"}},
|
|
{Data: ElemData{ID: "e01", Source: "n01", Target: "n02"}, Classes: "bezier"},
|
|
{Data: ElemData{ID: "e02", Source: "n01", Target: "n02"}, Classes: "bezier"},
|
|
{Data: ElemData{ID: "e03", Source: "n02", Target: "n01"}, Classes: "bezier"},
|
|
{Data: ElemData{ID: "n03", Attributes: map[string]interface{}{"type": "unbundled-bezier"}}},
|
|
{Data: ElemData{ID: "n04"}},
|
|
{Data: ElemData{ID: "e04", Source: "n03", Target: "n04"}, Classes: "unbundled-bezier"},
|
|
{Data: ElemData{ID: "n05", Attributes: map[string]interface{}{"type": "unbundled-bezier(multiple)"}}},
|
|
{Data: ElemData{ID: "n06"}},
|
|
{Data: ElemData{ID: "e05", Source: "n05", Target: "n06", Parent: ""}, Classes: "multi-unbundled-bezier"},
|
|
{Data: ElemData{ID: "n07", Attributes: map[string]interface{}{"type": "haystack"}}},
|
|
{Data: ElemData{ID: "n08"}},
|
|
{Data: ElemData{ID: "e06", Source: "n08", Target: "n07"}, Classes: "haystack"},
|
|
{Data: ElemData{ID: "e07", Source: "n08", Target: "n07"}, Classes: "haystack"},
|
|
{Data: ElemData{ID: "e08", Source: "n08", Target: "n07"}, Classes: "haystack"},
|
|
{Data: ElemData{ID: "e09", Source: "n08", Target: "n07"}, Classes: "haystack"},
|
|
{Data: ElemData{ID: "n09", Attributes: map[string]interface{}{"type": "segments"}}},
|
|
{Data: ElemData{ID: "n10"}},
|
|
{Data: ElemData{ID: "e10", Source: "n09", Target: "n10"}, Classes: "segments"},
|
|
},
|
|
},
|
|
}
|
|
|
|
func TestUnmarshalElements(t *testing.T) {
|
|
for _, test := range cytoscapejsElementsTests {
|
|
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 []Element
|
|
err = json.Unmarshal(data, &got)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
var gotNodes, gotEdges int
|
|
for _, e := range got {
|
|
typ, err := e.Type()
|
|
if err != nil {
|
|
t.Errorf("unexpected error finding element type for %+v: %v", e, err)
|
|
}
|
|
switch typ {
|
|
case NodeElement:
|
|
gotNodes++
|
|
case EdgeElement:
|
|
gotEdges++
|
|
}
|
|
}
|
|
|
|
if gotNodes != test.wantNodes {
|
|
t.Errorf("unexpected result for order of %q: got:%d want:%d", test.path, gotNodes, test.wantNodes)
|
|
}
|
|
if gotEdges != test.wantEdges {
|
|
t.Errorf("unexpected result for size of %q: got:%d want:%d", test.path, gotEdges, test.wantEdges)
|
|
}
|
|
if test.wantGraph != nil && !reflect.DeepEqual(got, test.wantGraph) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got, test.wantGraph)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMarshalElements(t *testing.T) {
|
|
for _, test := range cytoscapejsElementsTests {
|
|
data, err := os.ReadFile(filepath.Join("testdata", test.path))
|
|
if err != nil {
|
|
t.Errorf("failed to read %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
var want []Element
|
|
err = json.Unmarshal(data, &want)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
marshaled, err := json.Marshal(want)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
var got []Element
|
|
err = json.Unmarshal(marshaled, &got)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
var cytoscapejsNodeEdgeTests = []struct {
|
|
path string
|
|
wantNodes int
|
|
wantEdges int
|
|
wantGraph *Elements
|
|
firstNode Node
|
|
firstEdge Edge
|
|
wantNodeAttributes map[string]bool
|
|
wantEdgeAttributes map[string]bool
|
|
}{
|
|
{
|
|
path: "cola-compound.json",
|
|
wantNodes: 9,
|
|
wantEdges: 7,
|
|
wantGraph: &Elements{
|
|
Nodes: []Node{
|
|
{Data: NodeData{ID: "compound-1", Parent: ""}},
|
|
{Data: NodeData{ID: "compound-2", Parent: ""}},
|
|
{Data: NodeData{ID: "compound-3", Parent: ""}},
|
|
{Data: NodeData{ID: "b", Parent: "compound-1"}},
|
|
{Data: NodeData{ID: "c", Parent: "compound-1"}},
|
|
{Data: NodeData{ID: "a", Parent: "compound-2"}},
|
|
{Data: NodeData{ID: "d", Parent: "compound-3"}},
|
|
{Data: NodeData{ID: "e", Parent: "compound-3"}},
|
|
{Data: NodeData{ID: "f", Parent: ""}},
|
|
},
|
|
Edges: []Edge{
|
|
{Data: EdgeData{ID: "ab", Source: "a", Target: "b"}},
|
|
{Data: EdgeData{ID: "bc", Source: "b", Target: "c"}},
|
|
{Data: EdgeData{ID: "ac", Source: "a", Target: "c"}},
|
|
{Data: EdgeData{ID: "cd", Source: "c", Target: "d"}},
|
|
{Data: EdgeData{ID: "de", Source: "d", Target: "e"}},
|
|
{Data: EdgeData{ID: "df", Source: "d", Target: "f"}},
|
|
{Data: EdgeData{ID: "af", Source: "a", Target: "f"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
path: "tokyo-railways.json",
|
|
wantNodes: 943,
|
|
wantEdges: 860,
|
|
firstNode: Node{
|
|
Data: NodeData{
|
|
ID: "8220",
|
|
Attributes: map[string]interface{}{
|
|
"station_name": "京成高砂",
|
|
"close_ymd": "",
|
|
"lon": 139.866875,
|
|
"post": "",
|
|
"e_status": 0.0,
|
|
"SUID": 8220.0,
|
|
"station_g_cd": 2300110.0,
|
|
"add": "東京都葛飾区高砂五丁目28-1",
|
|
"line_cd": 99340.0,
|
|
"selected": false,
|
|
"open_ymd": "",
|
|
"name": "9934001",
|
|
"pref_name": "東京都",
|
|
"shared_name": "9934001",
|
|
"lat": 35.750932,
|
|
"x": 1398668.75,
|
|
"y": -357509.32,
|
|
},
|
|
},
|
|
Position: &Position{
|
|
X: 1398668.75,
|
|
Y: -357509.32,
|
|
},
|
|
},
|
|
firstEdge: Edge{
|
|
Data: EdgeData{
|
|
ID: "18417",
|
|
Source: "8220",
|
|
Target: "8221",
|
|
Attributes: map[string]interface{}{
|
|
"line_name_k": "ホクソウテツドウホクソウセン",
|
|
"is_bullet": false,
|
|
"lon": 140.03784499075186,
|
|
"company_name_k": "ホクソウテツドウ",
|
|
"zoom": 11.0,
|
|
"SUID": 18417.0,
|
|
"company_type": 0.0,
|
|
"company_name_h": "北総鉄道株式会社",
|
|
"interaction": "99340",
|
|
"shared_interaction": "99340",
|
|
"company_url": "http://www.hokuso-railway.co.jp/",
|
|
"line_name": "北総鉄道北総線",
|
|
"selected": false,
|
|
"company_name": "北総鉄道",
|
|
"company_cd": 152.0,
|
|
"name": "9934001 (99340) 9934002",
|
|
"rr_cd": 99.0,
|
|
"company_name_r": "北総鉄道",
|
|
"e_status_x": 0.0,
|
|
"shared_name": "9934001 (99340) 9934002",
|
|
"lat": 35.78346285846615,
|
|
"e_status_y": 0.0,
|
|
"line_name_h": "北総鉄道北総線",
|
|
},
|
|
},
|
|
},
|
|
wantNodeAttributes: map[string]bool{
|
|
"station_name": true,
|
|
"close_ymd": true,
|
|
"lon": true,
|
|
"post": true,
|
|
"e_status": true,
|
|
"SUID": true,
|
|
"station_g_cd": true,
|
|
"add": true,
|
|
"line_cd": true,
|
|
"selected": true,
|
|
"open_ymd": true,
|
|
"name": true,
|
|
"pref_name": true,
|
|
"shared_name": true,
|
|
"lat": true,
|
|
"x": true,
|
|
"y": true,
|
|
},
|
|
wantEdgeAttributes: map[string]bool{
|
|
"line_name_k": true,
|
|
"is_bullet": true,
|
|
"lon": true,
|
|
"company_name_k": true,
|
|
"zoom": true,
|
|
"SUID": true,
|
|
"company_type": true,
|
|
"company_name_h": true,
|
|
"interaction": true,
|
|
"shared_interaction": true,
|
|
"company_url": true,
|
|
"line_name": true,
|
|
"selected": true,
|
|
"company_name": true,
|
|
"company_cd": true,
|
|
"name": true,
|
|
"rr_cd": true,
|
|
"company_name_r": true,
|
|
"e_status_x": true,
|
|
"shared_name": true,
|
|
"lat": true,
|
|
"e_status_y": true,
|
|
"line_name_h": true,
|
|
},
|
|
},
|
|
}
|
|
|
|
func TestUnmarshalNodeEdge(t *testing.T) {
|
|
for _, test := range cytoscapejsNodeEdgeTests {
|
|
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 Elements
|
|
err = json.Unmarshal(data, &got)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
|
|
if len(got.Nodes) != test.wantNodes {
|
|
t.Errorf("unexpected result for order of %q: got:%d want:%d", test.path, len(got.Nodes), test.wantNodes)
|
|
}
|
|
if len(got.Edges) != test.wantEdges {
|
|
t.Errorf("unexpected result for size of %q: got:%d want:%d", test.path, len(got.Edges), test.wantEdges)
|
|
}
|
|
if test.wantGraph != nil {
|
|
if !reflect.DeepEqual(&got, test.wantGraph) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got.Nodes, test.wantGraph.Nodes)
|
|
}
|
|
} else {
|
|
if !reflect.DeepEqual(got.Nodes[0], test.firstNode) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got.Nodes[0], test.firstNode)
|
|
}
|
|
if !reflect.DeepEqual(got.Edges[0], test.firstEdge) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%v\nwant:\n%#v", test.path, got.Edges[0].Data.Source, test.firstEdge.Data.Source)
|
|
}
|
|
}
|
|
if test.wantNodeAttributes != nil {
|
|
var paths []string
|
|
for _, n := range got.Nodes {
|
|
paths = attrPaths(paths, "", n.Data.Attributes)
|
|
}
|
|
gotAttrs := make(map[string]bool)
|
|
for _, p := range paths {
|
|
gotAttrs[p] = true
|
|
}
|
|
if !reflect.DeepEqual(gotAttrs, test.wantNodeAttributes) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, gotAttrs, test.wantNodeAttributes)
|
|
}
|
|
}
|
|
if test.wantEdgeAttributes != nil {
|
|
var paths []string
|
|
for _, e := range got.Edges {
|
|
paths = attrPaths(paths, "", e.Data.Attributes)
|
|
}
|
|
gotAttrs := make(map[string]bool)
|
|
for _, p := range paths {
|
|
gotAttrs[p] = true
|
|
}
|
|
if !reflect.DeepEqual(gotAttrs, test.wantEdgeAttributes) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, gotAttrs, test.wantEdgeAttributes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMarshalNodeEdge(t *testing.T) {
|
|
for _, test := range cytoscapejsNodeEdgeTests {
|
|
data, err := os.ReadFile(filepath.Join("testdata", test.path))
|
|
if err != nil {
|
|
t.Errorf("failed to read %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
var want Elements
|
|
err = json.Unmarshal(data, &want)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
marshaled, err := json.Marshal(want)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
var got Elements
|
|
err = json.Unmarshal(marshaled, &got)
|
|
if err != nil {
|
|
t.Errorf("failed to unmarshal %q: %v", test.path, err)
|
|
continue
|
|
}
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("unexpected result for %q:\ngot:\n%#v\nwant:\n%#v", test.path, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func attrPaths(dst []string, prefix string, m map[string]interface{}) []string {
|
|
for k, v := range m {
|
|
path := prefix
|
|
if path != "" {
|
|
path += "."
|
|
}
|
|
if v, ok := v.(map[string]interface{}); ok {
|
|
dst = attrPaths(dst, path+k, v)
|
|
}
|
|
dst = append(dst, path+k)
|
|
}
|
|
return dst
|
|
}
|