|
@@ -0,0 +1,375 @@
|
|
|
|
+/*
|
|
|
|
+ * 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 dbfunc
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "fmt"
|
|
|
|
+ "testing"
|
|
|
|
+
|
|
|
|
+ "devt.de/krotik/eliasdb/graph"
|
|
|
|
+ "devt.de/krotik/eliasdb/graph/graphstorage"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+func TestStoreAndRemoveNode(t *testing.T) {
|
|
|
|
+
|
|
|
|
+ mgs := graphstorage.NewMemoryGraphStorage("mystorage")
|
|
|
|
+ gm := graph.NewGraphManager(mgs)
|
|
|
|
+
|
|
|
|
+ sn := &StoreNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := sn.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires 2 or 3 parameters: partition, node map and optionally a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"", "bla"}); err == nil ||
|
|
|
|
+ err.Error() != "Second parameter must be a map" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{}, "bla"}); err == nil ||
|
|
|
|
+ err.Error() != "Third parameter must be a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo",
|
|
|
|
+ }}); err == nil ||
|
|
|
|
+ err.Error() != "GraphError: Invalid data (Node is missing a kind value)" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ "data": "123",
|
|
|
|
+ "data2": "1234",
|
|
|
|
+ }}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 1 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ un := &UpdateNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := un.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires 2 or 3 parameters: partition, node map and optionally a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{"", "bla"}); err == nil ||
|
|
|
|
+ err.Error() != "Second parameter must be a map" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{}, "bla"}); err == nil ||
|
|
|
|
+ err.Error() != "Third parameter must be a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo",
|
|
|
|
+ }}); err == nil ||
|
|
|
|
+ err.Error() != "GraphError: Invalid data (Node is missing a kind value)" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ "data": "1234",
|
|
|
|
+ }}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 1 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn := &FetchNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := fn.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := fn.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires 3 parameters: partition, node key node kind" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := fn.Run("", nil, nil, 0, []interface{}{"main", "foo", "ba r"}); err == nil ||
|
|
|
|
+ err.Error() != "GraphError: Invalid data (Node kind ba r is not alphanumeric - can only contain [a-zA-Z0-9_])" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ res, err := fn.Run("", nil, nil, 0, []interface{}{"main", "foo", "bar"})
|
|
|
|
+
|
|
|
|
+ if fmt.Sprint(NewGraphNodeFromECALMap(res.(map[interface{}]interface{}))) != `
|
|
|
|
+GraphNode:
|
|
|
|
+ key : foo
|
|
|
|
+ kind : bar
|
|
|
|
+ data : 1234
|
|
|
|
+ data2 : 1234
|
|
|
|
+`[1:] || err != nil {
|
|
|
|
+ t.Error("Unexpected result:\n", res, err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rn := &RemoveNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := rn.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := rn.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires 3 or 4 parameters: partition, node key node kind and optionally a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := rn.Run("", nil, nil, 0, []interface{}{"mai n", "foo", "bar"}); err == nil ||
|
|
|
|
+ err.Error() != "GraphError: Invalid data (Partition name mai n is not alphanumeric - can only contain [a-zA-Z0-9_])" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = rn.Run("", nil, nil, 0, []interface{}{"main", "foo", "bar"})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ res, err = fn.Run("", nil, nil, 0, []interface{}{"main", "foo", "bar"})
|
|
|
|
+ if res != nil || err != nil {
|
|
|
|
+ t.Error("Unexpected result:", res, err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func TestStoreNodeTrans(t *testing.T) {
|
|
|
|
+ mgs := graphstorage.NewMemoryGraphStorage("mystorage")
|
|
|
|
+ gm := graph.NewGraphManager(mgs)
|
|
|
|
+
|
|
|
|
+ tn := &NewTransFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := tn.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tn2 := &NewRollingTransFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := tn2.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tc := &CommitTransFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := tc.DocString(); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := tn.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Function does not require any parameters" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if _, err := tn2.Run("", nil, nil, 0, []interface{}{"", ""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires the rolling threshold (number of operations before rolling)" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if _, err := tc.Run("", nil, nil, 0, []interface{}{"", ""}); err == nil ||
|
|
|
|
+ err.Error() != "Function requires the transaction to commit as parameter" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := tc.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
|
|
|
|
+ err.Error() != "Parameter must be a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ trans, err := tn.Run("", nil, nil, 0, []interface{}{})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = tn2.Run("", nil, nil, 0, []interface{}{"foo"})
|
|
|
|
+ if err == nil || err.Error() != "Rolling threshold must be a number not: foo" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = tn2.Run("", nil, nil, 0, []interface{}{1})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sn := &StoreNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo1",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ }, trans}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo2",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ }, trans}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ un := &UpdateNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ if _, err := un.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo3",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ }, trans}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check that the nodes are in the transaction
|
|
|
|
+
|
|
|
|
+ if res := fmt.Sprint(trans.(graph.Trans).Counts()); res != "3 0 0 0" {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 0 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Commit the nodes
|
|
|
|
+
|
|
|
|
+ if _, err := tc.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
|
|
|
|
+ "key": "foo3",
|
|
|
|
+ "kind": "bar",
|
|
|
|
+ }, trans}); err == nil || err.Error() != "Function requires the transaction to commit as parameter" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if _, err := tc.Run("", nil, nil, 0, []interface{}{trans}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check that the nodes have been committed
|
|
|
|
+
|
|
|
|
+ if res := fmt.Sprint(trans.(graph.Trans).Counts()); res != "0 0 0 0" {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 3 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Remove the nodes
|
|
|
|
+
|
|
|
|
+ rn := &RemoveNodeFunc{gm}
|
|
|
|
+
|
|
|
|
+ _, err = rn.Run("", nil, nil, 0, []interface{}{"main", "foo1", "bar", nil})
|
|
|
|
+ if err == nil || err.Error() != "Fourth parameter must be a transaction" {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = rn.Run("", nil, nil, 0, []interface{}{"main", "foo1", "bar", trans})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = rn.Run("", nil, nil, 0, []interface{}{"main", "foo2", "bar", trans})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, err = rn.Run("", nil, nil, 0, []interface{}{"main", "foo3", "bar", trans})
|
|
|
|
+ if err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check that the nodes are in the transaction
|
|
|
|
+
|
|
|
|
+ if res := fmt.Sprint(trans.(graph.Trans).Counts()); res != "0 0 3 0" {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 3 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Commit the nodes
|
|
|
|
+
|
|
|
|
+ if _, err := tc.Run("", nil, nil, 0, []interface{}{trans}); err != nil {
|
|
|
|
+ t.Error(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check that the nodes have been committed
|
|
|
|
+
|
|
|
|
+ if res := fmt.Sprint(trans.(graph.Trans).Counts()); res != "0 0 0 0" {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if res := gm.NodeCount("bar"); res != 0 {
|
|
|
|
+ t.Error("Unexpected result:", res)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+}
|