123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package graph
- import (
- "bytes"
- "io"
- "strings"
- "testing"
- "devt.de/krotik/eliasdb/graph/data"
- "devt.de/krotik/eliasdb/graph/graphstorage"
- "devt.de/krotik/eliasdb/storage"
- )
- func TestImportExportError(t *testing.T) {
- var res bytes.Buffer
- // Create a memory only storage
- gs := graphstorage.NewMemoryGraphStorage("test")
- gm := NewGraphManager(gs)
- // Test incomplete import data
- err := ImportPartition(bytes.NewBufferString(`
- {
- "nodes" : [
- {
- "key": "1",
- "kind": "X",
- `), "main", gm)
- if err == nil || err.Error() != "Could not decode file content as object with list of nodes and edges: unexpected EOF" {
- t.Error("Unexpected result:", err)
- return
- }
- // Export an empty graph
- err = ExportPartition(&res, "aaa", gm)
- if err != nil || res.String() != `{
- "nodes" : [
- ],
- "edges" : [
- ]
- }` {
- t.Error("Unexpected result:", res.String(), err)
- return
- }
- // Try exporting nodes with unexportable attibutes
- err = gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
- "key": "123",
- "kind": "bla",
- "test": data.NewGraphNode,
- }))
- if err != nil {
- t.Error(err)
- return
- }
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- sortRes := SortDump(res.String())
- if err != nil || sortRes != `{
- "edges": [],
- "nodes": [
- {
- "key": "123",
- "kind": "bla",
- "test": null
- }
- ]
- }` {
- t.Error("Unexpected result:", sortRes, err)
- return
- }
- // Error when reading a node
- msm := gs.StorageManager("main"+"bla"+StorageSuffixNodes, false).(*storage.MemoryStorageManager)
- msm.AccessMap[1] = storage.AccessCacheAndFetchSeriousError
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if !strings.HasPrefix(err.Error(), "GraphError: Failed to access graph storage component") {
- t.Error("Unexpected graph error:", err)
- return
- }
- delete(msm.AccessMap, 1)
- err = gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
- "key": "456",
- "kind": "bla",
- "test": data.NewGraphNode,
- }))
- msm = gs.StorageManager("main"+"bla"+StorageSuffixNodes, false).(*storage.MemoryStorageManager)
- msm.AccessMap[6] = storage.AccessCacheAndFetchSeriousError
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
- t.Error("Unexpected graph error:", err)
- return
- }
- delete(msm.AccessMap, 6)
- msm.AccessMap[5] = storage.AccessCacheAndFetchSeriousError
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
- t.Error("Unexpected graph error:", err)
- return
- }
- delete(msm.AccessMap, 5)
- gm.StoreEdge("main", data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(map[string]interface{}{
- "end1cascading": false,
- "end1key": "123",
- "end1kind": "bla",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "456",
- "end2kind": "bla",
- "end2role": "node",
- "key": "3",
- "kind": "xxx",
- })))
- // Traverse to relationship should fail
- msm.AccessMap[7] = storage.AccessCacheAndFetchSeriousError
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
- t.Error("Unexpected graph error:", err)
- return
- }
- delete(msm.AccessMap, 7)
- // Lookup of relationship should fail
- msm = gs.StorageManager("main"+"xxx"+StorageSuffixEdges, false).(*storage.MemoryStorageManager)
- msm.AccessMap[1] = storage.AccessCacheAndFetchSeriousError
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if !strings.HasPrefix(err.Error(), "GraphError: Failed to access graph storage component") {
- t.Error("Unexpected graph error:", err)
- return
- }
- delete(msm.AccessMap, 1)
- // Test invalid import data
- err = ImportPartition(bytes.NewBufferString(`{
- "nodes" : [
- {
- "key": "1",
- "kind": "X"
- },
- {
- "key": "2"
- }
- ],
- "edges" : [
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "4",
- "kind": "A"
- }
- ]
- }`), "main", gm)
- if err == nil || err.Error() != "GraphError: Invalid data (Node is missing a kind value)" {
- t.Error("Unexpected result:", err)
- return
- }
- err = ImportPartition(bytes.NewBufferString(`{
- "nodes" : [
- {
- "key": "1",
- "kind": "X"
- },
- {
- "key": "2",
- "kind": "Y"
- }
- ],
- "edges" : [
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "4",
- "kind": "A"
- }
- ]
- }`), "main", gm)
- if err == nil || err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end2)" {
- t.Error("Unexpected result:", err)
- return
- }
- // Do actual import and exports
- gs = graphstorage.NewMemoryGraphStorage("test")
- gm = NewGraphManager(gs)
- err = ImportPartition(bytes.NewBufferString(`{
- "nodes" : [
- {
- "key": "1",
- "kind": "X"
- },
- {
- "key": "2",
- "kind": "Y"
- }
- ],
- "edges" : [
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "4",
- "kind": "A"
- },
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "5",
- "kind": "B"
- }
- ]
- }`), "main", gm)
- if err != nil {
- t.Error(err)
- return
- }
- err = ImportPartition(bytes.NewBufferString(`{
- "nodes" : [
- {
- "key": "1",
- "kind": "Xfoo"
- },
- {
- "key": "2",
- "kind": "Yfoo"
- }
- ],
- "edges" : [
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "Xfoo",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Yfoo",
- "end2role": "node",
- "key": "4",
- "kind": "Afoo"
- },
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "Xfoo",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Yfoo",
- "end2role": "node",
- "key": "5",
- "kind": "Bfoo"
- }
- ]
- }`), "foo", gm)
- if err != nil {
- t.Error(err)
- return
- }
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- sortRes = SortDump(res.String())
- if err != nil || sortRes != `{
- "edges": [
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "4",
- "kind": "A"
- },
- {
- "end1cascading": false,
- "end1key": "1",
- "end1kind": "X",
- "end1role": "node",
- "end2cascading": false,
- "end2key": "2",
- "end2kind": "Y",
- "end2role": "node",
- "key": "5",
- "kind": "B"
- }
- ],
- "nodes": [
- {
- "key": "1",
- "kind": "X"
- },
- {
- "key": "2",
- "kind": "Y"
- }
- ]
- }` {
- t.Error("Unexpected result:", sortRes, err)
- return
- }
- // Do an import with the export data and see that nothing changes
- err = ImportPartition(bytes.NewBufferString(sortRes), "main", gm)
- if err != nil {
- t.Error(err)
- return
- }
- res.Reset()
- err = ExportPartition(&res, "main", gm)
- if err != nil {
- t.Error(err)
- return
- }
- sortRes2 := SortDump(res.String())
- if sortRes2 != sortRes {
- t.Error("Export data differs from import data:", sortRes2)
- return
- }
- }
- type testFactory struct {
- readers []string
- buf map[string]*bytes.Buffer
- }
- func (tf *testFactory) CreateWriter(name string) (io.Writer, error) {
- var b bytes.Buffer
- tf.readers = append(tf.readers, name)
- tf.buf[name] = &b
- return &b, nil
- }
- func (tf *testFactory) Readers() ([]string, error) {
- return tf.readers, nil
- }
- func (tf *testFactory) CreateReader(name string) (io.Reader, error) {
- return bytes.NewBuffer(tf.buf[name].Bytes()), nil
- }
- func TestScaleExport(t *testing.T) {
- gm, _ := songGraph()
- tf := &testFactory{make([]string, 0), make(map[string]*bytes.Buffer)}
- if err := LargeScaleExportPartition(tf, gm); err != nil {
- t.Error(err)
- return
- }
- var out1 bytes.Buffer
- if err := ExportPartition(&out1, "main", gm); err != nil {
- t.Error(err)
- return
- }
- res1 := SortDump(out1.String())
- mgs2 := graphstorage.NewMemoryGraphStorage("mystorage2")
- gm2 := NewGraphManager(mgs2)
- if err := LargeScaleImportPartition(tf, gm2); err != nil {
- t.Error(err)
- return
- }
- var out2 bytes.Buffer
- if err := ExportPartition(&out2, "main", gm2); err != nil {
- t.Error(err)
- return
- }
- res2 := SortDump(out2.String())
- if res1 != res2 {
- t.Error("Unexpected result - results of import/export are different")
- return
- }
- // Test failures
- gm, gs := songGraph()
- tfImport := tf
- tf = &testFactory{make([]string, 0), make(map[string]*bytes.Buffer)}
- msm := gs.StorageManager("main"+"Song"+StorageSuffixNodes, false).(*storage.MemoryStorageManager)
- msm.AccessMap[5] = storage.AccessCacheAndFetchSeriousError
- if err := LargeScaleExportPartition(tf, gm); err == nil {
- t.Error("Error was expected")
- return
- }
- delete(msm.AccessMap, 5)
- msm = gs.StorageManager("main"+"Wrote"+StorageSuffixEdges, false).(*storage.MemoryStorageManager)
- msm.AccessMap[5] = storage.AccessCacheAndFetchSeriousError
- if err := LargeScaleExportPartition(tf, gm); err == nil {
- t.Error("Error was expected")
- return
- }
- delete(msm.AccessMap, 5)
- mgs2 = graphstorage.NewMemoryGraphStorage("mystorage2")
- gm2 = NewGraphManager(mgs2)
- msm = mgs2.StorageManager("main"+"Song"+StorageSuffixNodes, true).(*storage.MemoryStorageManager)
- msm.AccessMap[2] = storage.AccessInsertError
- if err := LargeScaleImportPartition(tfImport, gm2); err == nil {
- t.Error("Error was expected")
- return
- }
- delete(msm.AccessMap, 2)
- }
|