// 18.9.2. Create node index with configuration func TestLegacyNodeIndexCreateWithConf(t *testing.T) { db := connectTest(t) name := rndStr(t) indexType := "fulltext" provider := "lucene" // // Create new index // idx0, err := db.CreateLegacyNodeIndex(name, indexType, provider) if err != nil { t.Error(err) } defer idx0.Delete() assert.Equal(t, idx0.IndexType, indexType) assert.Equal(t, idx0.Provider, provider) assert.Equal(t, idx0.Name, name) // // Get the index we just created // idx1, err := db.LegacyNodeIndex(name) if err != nil { t.Error(err) } assert.Equal(t, idx0.Name, idx1.Name) }
// The underlying functions are used for node and relationship indexes. For // now we will test only the pieces of code that are relationship-specific. func TestRelationshipIndexes(t *testing.T) { db := connectTest(t) name := rndStr(t) // // Create new index // idx0, err := db.CreateLegacyRelIndex(name, "", "") if err != nil { t.Fatal(err) } defer idx0.Delete() assert.Equal(t, idx0.Name, name) // // Get the index we just created // idx1, err := db.LegacyRelIndex(name) if err != nil { t.Fatal(err) } assert.Equal(t, idx0.Name, idx1.Name) // // See if we get this index, and only this index // indexes, err := db.LegacyRelIndexes() if err != nil { t.Fatal(err) } assert.Equal(t, 1, len(indexes)) idx2 := indexes[0] assert.Equal(t, idx0.Name, idx2.Name) }
// 18.4.2. Create Node with properties func TestGetOrCreateNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) label, err := randutil.String(12, randutil.Alphabet) if err != nil { t.Fatal(err) } key, err := randutil.String(12, randutil.Alphabet) if err != nil { t.Fatal(err) } value, err := randutil.String(12, randutil.Alphabet) if err != nil { t.Fatal(err) } p0 := Props{key: value, "foo": "bar"} p1 := Props{key: value} p2 := Props{"foo": "bar"} // // Create unique node // n0, created, err := db.GetOrCreateNode(label, key, p0) if err != nil { t.Fatal(err) } if !created { t.Fatal("Failed to create unique node") } check0, err := n0.Properties() if err != nil { t.Fatal(err) } assert.Equal(t, p0, check0) // // Get unique node // n1, created, err := db.GetOrCreateNode(label, key, p1) if err != nil { t.Fatal(err) } if created { t.Fatal("Failed to retrieve unique node") } check1, err := n1.Properties() if err != nil { t.Fatal(err) } assert.Equal(t, p0, check1) // // No key in props // _, _, err = db.GetOrCreateNode(label, key, p2) assert.NotEqual(t, nil, err) // // Empty label // _, _, err = db.GetOrCreateNode("", key, p0) assert.NotEqual(t, nil, err) }
func TestLabelsInvalidNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) n0, _ := db.CreateNode(nil) n0.Delete() err := n0.AddLabel("foobar") assert.Equal(t, NotFound, err) _, err = n0.Labels() assert.Equal(t, NotFound, err) }
func TestPatch(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(HandlePatch)) defer srv.Close() url := "http://" + srv.Listener.Addr().String() res := structType{} resp, err := Patch(url, &fooStruct, &res, nil) if err != nil { t.Error(err) } assert.Equal(t, resp.Status(), 200) // Server should return NO data assert.Equal(t, resp.RawText(), "") }
func TestTxCommit(t *testing.T) { db := connectTest(t) defer cleanup(t, db) name := rndStr(t) qs := []*CypherQuery{ &CypherQuery{ Statement: ` CREATE (n:Person {name: {name}}) RETURN n `, Parameters: Props{"name": name}, }, } tx, err := db.Begin(qs) if err != nil { t.Fatal(err) } // // Confirm it does not exist before commit // res0 := []struct { N string `json:"n.name"` }{} q0 := CypherQuery{ Statement: ` MATCH (n:Person) WHERE n.name = {name} RETURN n.name `, Parameters: Props{"name": name}, Result: &res0, } err = db.Cypher(&q0) if err != nil { t.Fatal(err) } assert.Equal(t, 0, len(res0)) // // Commit and confirm creation // err = tx.Commit() if err != nil { t.Fatal(err) } err = db.Cypher(&q0) if err != nil { t.Fatal(err) } assert.Equal(t, 1, len(res0)) }
// Test multi-line Cypher query with embedded comments. func TestCypherComment(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create idx0, _ := db.CreateLegacyNodeIndex("name_index", "", "") defer idx0.Delete() n0, _ := db.CreateNode(Props{"name": "I"}) idx0.Add(n0, "name", "I") n1, _ := db.CreateNode(Props{"name": "you", "age": 69}) n0.Relate("know", n1.Id(), nil) // Query // query := "START x = node:name_index(name=I) MATCH path = (x-[r]-friend) WHERE friend.name = you RETURN TYPE(r)" type resultStruct struct { Type string `json:"type(r)"` Name string `json:"n.name"` Age int `json:"n.age"` } result := []resultStruct{} stmt := ` START x = NODE(%d) // This is a comment MATCH x -[r]-> n // This is another comment RETURN TYPE(r), n.name, n.age ` stmt = fmt.Sprintf(stmt, n0.Id()) cq := CypherQuery{ Statement: stmt, Result: &result, } err := db.Cypher(&cq) if err != nil { t.Error(err) } // Check result // // Our test only passes if Neo4j returns columns in the expected order - is // there any guarantee about order? expCol := []string{"TYPE(r)", "n.name", "n.age"} expDat := []resultStruct{ resultStruct{ Type: "know", Name: "you", Age: 69, }, } assert.Equal(t, expCol, cq.Columns()) assert.Equal(t, expDat, result) }
func TestSetLabels(t *testing.T) { db := connectTest(t) defer cleanup(t, db) n0, _ := db.CreateNode(nil) n0.AddLabel("spam", "eggs") err := n0.SetLabels([]string{"foobar"}) if err != nil { t.Fatal(err) } labels, _ := n0.Labels() assert.Equal(t, []string{"foobar"}, labels) n0.Delete() err = n0.SetLabels([]string{"foobar"}) assert.Equal(t, NotFound, err) }
func TestPost(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(HandlePost)) defer srv.Close() s := Session{} s.Log = true url := "http://" + srv.Listener.Addr().String() payload := fooStruct res := structType{} resp, err := s.Post(url, &payload, &res, nil) if err != nil { t.Error(err) } assert.Equal(t, 200, resp.Status()) assert.Equal(t, res, barStruct) }
// 18.9.9. Find node by exact match func TestFindNodeByExactMatch(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create idxName := rndStr(t) key0 := rndStr(t) key1 := rndStr(t) value0 := rndStr(t) value1 := rndStr(t) idx0, _ := db.CreateLegacyNodeIndex(idxName, "", "") defer idx0.Delete() n0, _ := db.CreateNode(Props{}) n1, _ := db.CreateNode(Props{}) n2, _ := db.CreateNode(Props{}) // These two will be located by Find() below idx0.Add(n0, key0, value0) idx0.Add(n1, key0, value0) // These two will NOT be located by Find() below idx0.Add(n2, key1, value0) idx0.Add(n2, key0, value1) // nodes, err := idx0.Find(key0, value0) if err != nil { t.Error(err) } // This query should have returned a map containing just two nodes, n1 and n0. assert.Equal(t, len(nodes), 2) _, present := nodes[n0.Id()] assert.Tf(t, present, "Find() failed to return node with id "+strconv.Itoa(n0.Id())) _, present = nodes[n1.Id()] assert.Tf(t, present, "Find() failed to return node with id "+strconv.Itoa(n1.Id())) }
// 18.7.7. Delete a named property from a node func TestDeleteNamedPropertyFromNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create props0 := Props{"foo": "bar"} props1 := Props{"foo": "bar", "spam": "eggs"} n0, _ := db.CreateNode(props1) // Delete err := n0.DeleteProperty("spam") if err != nil { t.Error(err) } // Confirm checkProps, _ := n0.Properties() assert.Equalf(t, props0, checkProps, "Failed to remove named property with DeleteProperty().") // // Delete non-existent property // err = n0.DeleteProperty("eggs") assert.NotEqual(t, nil, err) // // Delete and check 404 // n0.Delete() err = n0.DeleteProperty("spam") assert.Equal(t, NotFound, err) }
func TestRemoveLabel(t *testing.T) { db := connectTest(t) defer cleanup(t, db) n0, _ := db.CreateNode(nil) n0.AddLabel("foobar") labels, _ := n0.Labels() assert.Equal(t, []string{"foobar"}, labels) err := n0.RemoveLabel("foobar") if err != nil { t.Fatal(err) } labels, _ = n0.Labels() assert.Equal(t, []string{}, labels) n0.Delete() err = n0.RemoveLabel("foobar") assert.Equal(t, NotFound, err) }
func TestNodesByLabel(t *testing.T) { db := connectTest(t) cleanup(t, db) // Make sure no nodes exist before we start defer cleanup(t, db) nodes, err := db.NodesByLabel("foobar") if err != nil { t.Fatal(err) } assert.Equal(t, 0, len(nodes)) n0, _ := db.CreateNode(nil) n0.AddLabel("foobar") nodes, err = db.NodesByLabel("foobar") if err != nil { t.Fatal(err) } exp := []*Node{n0} assert.Equal(t, exp, nodes) }
func TestDelete(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(HandleDelete)) defer srv.Close() url := "http://" + srv.Listener.Addr().String() resp, err := Delete(url, nil, nil) if err != nil { t.Error(err) } assert.Equal(t, 200, resp.Status()) }
func TestTxBegin(t *testing.T) { db := connectTest(t) defer cleanup(t, db) type name struct { Name string `json:"name"` } res0 := []resStruct0{} res1 := []resStruct1{} res2 := []resStruct2{} q0 := CypherQuery{ Statement: "CREATE (n:Person {props}) RETURN n", Parameters: map[string]interface{}{"props": map[string]string{"name": "James T Kirk"}}, Result: &res0, } q1 := CypherQuery{ Statement: "CREATE (m:Person {name: \"Dr McCoy\"}) RETURN m", Result: &res1, } q2 := CypherQuery{ Statement: ` MATCH (a:Person), (b:Person) WHERE a.name = "James T Kirk" AND b.name = "Dr McCoy" CREATE a-[r:Commands]->b RETURN a.name, type(r), b `, Parameters: map[string]interface{}{ "n_name": "James T Kirk", "m_name": "dr mccoy", }, Result: &res2, } assert.Equal(t, *new([]string), q1.Columns()) stmts := []*CypherQuery{&q0, &q1, &q2} tx, err := db.Begin(stmts) tx.Rollback() if err != nil { t.Fatal(err) } assert.Equal(t, 1, len(res0)) assert.Equal(t, "James T Kirk", res0[0].N.Name) assert.Equal(t, 1, len(res1)) assert.Equal(t, "Dr McCoy", res1[0].M["name"]) assert.Equal(t, 1, len(res2)) assert.Equal(t, "James T Kirk", res2[0].A) assert.Equal(t, "Commands", res2[0].Rel) assert.Equal(t, "Dr McCoy", res2[0].B.Name) }
// 18.4.4. Get non-existent node func TestGetNonexistentNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create a node n0, _ := db.CreateNode(Props{}) // Try to get non-existent node with next Id implausible := n0.Id() + 1000 _, err := db.Node(implausible) assert.Equal(t, err, NotFound) }
func TestRelationshipStartEnd(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create start, _ := db.CreateNode(Props{}) end, _ := db.CreateNode(Props{}) r0, _ := start.Relate("knows", end.Id(), Props{}) // n, err := r0.Start() if err != nil { t.Fatal(err) } assert.Equal(t, start, n) n, err = r0.End() if err != nil { t.Fatal(err) } assert.Equal(t, end, n) }
func TestOptions(t *testing.T) { // TODO: test result srv := httptest.NewServer(http.HandlerFunc(HandleOptions)) defer srv.Close() url := "http://" + srv.Listener.Addr().String() resp, err := Options(url, nil, nil) if err != nil { t.Error(err) } assert.Equal(t, 200, resp.Status()) }
func TestAddLabels(t *testing.T) { db := connectTest(t) defer cleanup(t, db) n0, _ := db.CreateNode(nil) labels, err := n0.Labels() if err != nil { t.Fatal(err) } assert.Equal(t, []string{}, labels) newLabels := []string{"Person", "Bicyclist"} err = n0.AddLabel(newLabels...) if err != nil { t.Fatal(err) } labels, err = n0.Labels() if err != nil { t.Fatal(err) } assert.Equal(t, newLabels, labels) }
// 18.4.5. Delete node func TestDeleteNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create then delete a node n0, _ := db.CreateNode(Props{}) id := n0.Id() err := n0.Delete() if err != nil { t.Error(err) } // Check that node is no longer in db _, err = db.Node(id) assert.Equal(t, err, NotFound) // // Delete non-existent node // err = n0.Delete() assert.Equal(t, NotFound, err) }
// 18.9.3. Delete node index func TestDeleteLegacyNodeIndex(t *testing.T) { db := connectTest(t) // Include a space in the name to ensure correct URL escaping. name := rndStr(t) + " " + rndStr(t) idx0, _ := db.CreateLegacyNodeIndex(name, "", "") err := idx0.Delete() if err != nil { t.Error(err) } _, err = db.LegacyNodeIndex(name) assert.Equal(t, err, NotFound) }
// TestDefaultParams tests using per-session default query parameters. func TestDefaultParams(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(HandleGet)) defer srv.Close() // // Good request // url := "http://" + srv.Listener.Addr().String() p := fooParams res := structType{} s := Session{ Params: &p, } resp, err := s.Get(url, nil, &res, nil) if err != nil { t.Error(err) } assert.Equal(t, 200, resp.Status()) assert.Equal(t, res, barStruct) // // Bad request // url = "http://" + srv.Listener.Addr().String() p = Params{"bad": "value"} e := errorStruct{} resp, err = Get(url, &p, nil, nil) if err != nil { t.Fatal(err) } if resp.Status() == 200 { t.Error("Server returned 200 success when it should have failed") } assert.Equal(t, 500, resp.Status()) expected := errorStruct{ Message: "Bad query params: bad=value", Status: 500, } resp.Unmarshal(&e) assert.Equal(t, e, expected) }
func TestRawRequestWithoutData(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(HandleRaw)) defer srv.Close() var payload *bytes.Buffer = nil res := structType{} req := Request{ Url: "http://" + srv.Listener.Addr().String(), Method: "PUT", RawPayload: true, Payload: payload, Result: &res, } resp, err := Send(&req) if err != nil { t.Error(err) } assert.Equal(t, resp.Status(), 200) assert.Equal(t, res.Bar, "empty") }
// 18.9.1. Create node index func TestCreateLegacyNodeIndex(t *testing.T) { db := connectTest(t) name := rndStr(t) // // Create new index // idx0, err := db.CreateLegacyNodeIndex(name, "", "") if err != nil { t.Error(err) } defer idx0.Delete() assert.Equal(t, idx0.Name, name) // // Get the index we just created // idx1, err := db.LegacyNodeIndex(name) if err != nil { t.Error(err) } assert.Equal(t, idx0.Name, idx1.Name) assert.Equal(t, idx0.HrefIndex, idx1.HrefIndex) }
// 18.5.1. Get Relationship by ID func TestGetRelationshipById(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create n0, _ := db.CreateNode(Props{}) n1, _ := db.CreateNode(Props{}) r0, _ := n0.Relate("knows", n1.Id(), Props{}) // Get relationship r1, err := db.Relationship(r0.Id()) if err != nil { t.Error(err) } assert.Equal(t, r0.Id(), r1.Id()) }
func TestTxQueryBad(t *testing.T) { db := connectTest(t) defer cleanup(t, db) qs0 := []*CypherQuery{} qs1 := []*CypherQuery{ &CypherQuery{ Statement: `foobar`, }, } tx, err := db.Begin(qs0) if err != nil { t.Fatal(err) } err = tx.Query(qs1) assert.Equal(t, TxQueryError, err) tx.Rollback() // Else cleanup will hang til Tx times out }
func TestNodeProperty(t *testing.T) { db := connectTest(t) defer cleanup(t, db) props := Props{"foo": "bar"} n0, _ := db.CreateNode(props) value, err := n0.Property("foo") if err != nil { t.Error(err) } assert.Equalf(t, value, "bar", "Incorrect value when getting single property.") // // Check Not Found // n0.Delete() _, err = n0.Property("foo") assert.Equal(t, NotFound, err) }
func TestTxRollback(t *testing.T) { db := connectTest(t) defer cleanup(t, db) qs0 := []*CypherQuery{ &CypherQuery{ Statement: `CREATE (n:Person)`, }, } tx, err := db.Begin(qs0) if err != nil { t.Fatal(err) } err = tx.Rollback() if err != nil { t.Fatal(err) } err = tx.Query(qs0) assert.Equal(t, NotFound, err) }
// 18.7.6. Delete all properties from node func TestDeleteAllPropertiesFromNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create props := Props{ rndStr(t): rndStr(t), rndStr(t): rndStr(t), } n0, _ := db.CreateNode(props) // Delete properties err := n0.DeleteProperties() if err != nil { t.Error(err) } // Confirm deletion checkProps, _ := n0.Properties() assert.Equalf(t, Props{}, checkProps, "Properties should be empty after call to DeleteProperties()") n0.Delete() err = n0.DeleteProperties() assert.Equal(t, NotFound, err) }
// 18.4.1. Create Node func TestCreateNode(t *testing.T) { db := connectTest(t) defer cleanup(t, db) // Create n0, err := db.CreateNode(nil) if err != nil { t.Error(err) } // Confirm creation _, err = db.Node(n0.Id()) if err != nil { t.Error(err) } // // Bad Href // db1 := connectTest(t) db1.HrefNode = db1.HrefNode + "foobar" _, err = db1.CreateNode(nil) assert.Equal(t, NotFound, err) }