| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 | /* * 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 v1import (	"bytes"	"encoding/json"	"flag"	"io/ioutil"	"net/http"	"os"	"strconv"	"strings"	"sync"	"testing"	"devt.de/krotik/common/errorutil"	"devt.de/krotik/common/httputil"	"devt.de/krotik/eliasdb/api"	"devt.de/krotik/eliasdb/eql"	"devt.de/krotik/eliasdb/graph"	"devt.de/krotik/eliasdb/graph/data"	"devt.de/krotik/eliasdb/graph/graphstorage")const TESTPORT = ":9090"var gmMSM *graphstorage.MemoryGraphStorage// Main function for all tests in this packagefunc TestMain(m *testing.M) {	flag.Parse()	gm, msm := filterGraph()	api.GM = gm	api.GS = msm	gmMSM = msm	hs, wg := startServer()	if hs == nil {		return	}	// Register endpoints for version 1	api.RegisterRestEndpoints(V1EndpointMap)	// Run the tests	res := m.Run()	// Teardown	stopServer(hs, wg)	os.Exit(res)}func TestSwaggerDefs(t *testing.T) {	// Test we can build swagger defs from the endpoint	data := map[string]interface{}{		"paths":       map[string]interface{}{},		"definitions": map[string]interface{}{},	}	for _, inst := range V1EndpointMap {		inst().SwaggerDefs(data)	}}/*Send a request to a HTTP test server*/func sendTestRequest(url string, method string, content []byte) (string, http.Header, string) {	var req *http.Request	var err error	if content != nil {		req, err = http.NewRequest(method, url, bytes.NewBuffer(content))	} else {		req, err = http.NewRequest(method, url, nil)	}	if err != nil {		panic(err)	}	req.Header.Set("Content-Type", "application/json")	client := &http.Client{}	resp, err := client.Do(req)	if err != nil {		panic(err)	}	defer resp.Body.Close()	body, _ := ioutil.ReadAll(resp.Body)	bodyStr := strings.Trim(string(body), " \n")	// Try json decoding first	out := bytes.Buffer{}	err = json.Indent(&out, []byte(bodyStr), "", "  ")	if err == nil {		return resp.Status, resp.Header, out.String()	}	// Just return the body	return resp.Status, resp.Header, bodyStr}/*formatJSONString formats a given JSON string.*/func formatJSONString(str string) string {	out := bytes.Buffer{}	errorutil.AssertOk(json.Indent(&out, []byte(str), "", "  "))	return out.String()}/*formatData returns a given datastructure as JSON string.*/func formatData(data interface{}) string {	actualResultBytes, _ := json.MarshalIndent(data, "", "  ")	return string(actualResultBytes)}/*Start a HTTP test server.*/func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {	hs := &httputil.HTTPServer{}	var wg sync.WaitGroup	wg.Add(1)	go hs.RunHTTPServer(TESTPORT, &wg)	wg.Wait()	// Server is started	if hs.LastError != nil {		panic(hs.LastError)	}	return hs, &wg}/*Stop a started HTTP test server.*/func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {	if hs.Running == true {		wg.Add(1)		// Server is shut down		hs.Shutdown()		wg.Wait()	} else {		panic("Server was not running as expected")	}}func songGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {	mgs := graphstorage.NewMemoryGraphStorage("mystorage")	gm := graph.NewGraphManager(mgs)	constructEdge := func(key string, node1 data.Node, node2 data.Node, number int) data.Edge {		edge := data.NewGraphEdge()		edge.SetAttr("key", key)		edge.SetAttr("kind", "Wrote")		edge.SetAttr(data.EdgeEnd1Key, node1.Key())		edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())		edge.SetAttr(data.EdgeEnd1Role, "Author")		edge.SetAttr(data.EdgeEnd1Cascading, true)		edge.SetAttr(data.EdgeEnd2Key, node2.Key())		edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())		edge.SetAttr(data.EdgeEnd2Role, "Song")		edge.SetAttr(data.EdgeEnd2Cascading, false)		edge.SetAttr("number", number)		return edge	}	storeSong := func(node data.Node, name string, ranking int, number int) {		node3 := data.NewGraphNode()		node3.SetAttr("key", name)		node3.SetAttr("kind", "Song")		node3.SetAttr("name", name)		node3.SetAttr("ranking", ranking)		gm.StoreNode("main", node3)		gm.StoreEdge("main", constructEdge(name, node, node3, number))	}	node0 := data.NewGraphNode()	node0.SetAttr("key", "000")	node0.SetAttr("kind", "Author")	node0.SetAttr("name", "John")	node0.SetAttr("desc", "One of the most popular acoustic artists of the decade and one of its best-selling artists.")	gm.StoreNode("main", node0)	gm.StoreNode("test", node0)  // Same node but different partition	gm.StoreNode("_test", node0) // Same node but different (hidden) partition	storeSong(node0, "Aria1", 8, 1)	storeSong(node0, "Aria2", 2, 2)	storeSong(node0, "Aria3", 4, 3)	storeSong(node0, "Aria4", 18, 4)	node1 := data.NewGraphNode()	node1.SetAttr("key", "123")	node1.SetAttr("kind", "Author")	node1.SetAttr("name", "Mike")	gm.StoreNode("main", node1)	storeSong(node1, "LoveSong3", 1, 3)	storeSong(node1, "FightSong4", 3, 4)	storeSong(node1, "DeadSong2", 6, 2)	storeSong(node1, "StrangeSong1", 5, 1)	node2 := data.NewGraphNode()	node2.SetAttr("key", "456")	node2.SetAttr("kind", "Author")	node2.SetAttr("name", "Hans")	gm.StoreNode("main", node2)	storeSong(node2, "MyOnlySong3", 19, 3)	// Create lots of spam nodes	for i := 0; i < 21; i++ {		nodespam := data.NewGraphNode()		nodespam.SetAttr("key", "000"+strconv.Itoa(i))		nodespam.SetAttr("kind", "Spam")		nodespam.SetAttr("name", "Spam"+strconv.Itoa(i))		gm.StoreNode("main", nodespam)	}	return gm, mgs.(*graphstorage.MemoryGraphStorage)}func songGraphGroups() (*graph.Manager, *graphstorage.MemoryGraphStorage) {	gm, mgs := songGraph()	node0 := data.NewGraphNode()	node0.SetAttr("key", "Best")	node0.SetAttr("kind", eql.GroupNodeKind)	gm.StoreNode("main", node0)	constructEdge := func(songkey string) data.Edge {		edge := data.NewGraphEdge()		edge.SetAttr("key", songkey)		edge.SetAttr("kind", "Contains")		edge.SetAttr(data.EdgeEnd1Key, node0.Key())		edge.SetAttr(data.EdgeEnd1Kind, node0.Kind())		edge.SetAttr(data.EdgeEnd1Role, "group")		edge.SetAttr(data.EdgeEnd1Cascading, false)		edge.SetAttr(data.EdgeEnd2Key, songkey)		edge.SetAttr(data.EdgeEnd2Kind, "Song")		edge.SetAttr(data.EdgeEnd2Role, "Song")		edge.SetAttr(data.EdgeEnd2Cascading, false)		return edge	}	gm.StoreEdge("main", constructEdge("LoveSong3"))	gm.StoreEdge("main", constructEdge("Aria3"))	gm.StoreEdge("main", constructEdge("MyOnlySong3"))	gm.StoreEdge("main", constructEdge("StrangeSong1"))	// Store additional groups	node0 = data.NewGraphNode()	node0.SetAttr("key", "foo")	node0.SetAttr("kind", eql.GroupNodeKind)	gm.StoreNode("main", node0)	node0 = data.NewGraphNode()	node0.SetAttr("key", "g1")	node0.SetAttr("kind", eql.GroupNodeKind)	gm.StoreNode("main", node0)	node0 = data.NewGraphNode()	node0.SetAttr("key", "g2")	node0.SetAttr("kind", eql.GroupNodeKind)	gm.StoreNode("main", node0)	return gm, mgs}func filterGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {	gm, mgs := songGraphGroups()	constructNode := func(key, val1, val2, val3 string) data.Node {		node0 := data.NewGraphNode()		node0.SetAttr("key", key)		node0.SetAttr("kind", "filtertest")		node0.SetAttr("val1", val1)		node0.SetAttr("val2", val2)		node0.SetAttr("val3", val3)		return node0	}	gm.StoreNode("main", constructNode("1", "test", "Hans", "foo"))	gm.StoreNode("main", constructNode("2", "test1", "Hans", "foo"))	gm.StoreNode("main", constructNode("3", "test2", "Hans", "foo"))	gm.StoreNode("main", constructNode("4", "test3", "Peter", "foo"))	gm.StoreNode("main", constructNode("5", "test4", "Peter", "foo"))	gm.StoreNode("main", constructNode("6", "test5", "Peter", "foo"))	gm.StoreNode("main", constructNode("7", "test6", "Anna", "foo"))	gm.StoreNode("main", constructNode("8", "test7", "Anna", "foo"))	gm.StoreNode("main", constructNode("9", "test8", "Steve", "foo"))	gm.StoreNode("main", constructNode("10", "test9", "Steve", "foo"))	gm.StoreNode("main", constructNode("11", "test10", "Franz", "foo"))	gm.StoreNode("main", constructNode("12", "test11", "Kevin", "foo"))	gm.StoreNode("main", constructNode("13", "test12", "Kevin", "foo"))	gm.StoreNode("main", constructNode("14", "test13", "Kevin", "foo"))	gm.StoreNode("main", constructNode("15", "test14", "X1", "foo"))	gm.StoreNode("main", constructNode("16", "test15", "X2", "foo"))	gm.StoreNode("main", constructNode("17", "test16", "X3", "foo"))	gm.StoreNode("main", constructNode("18", "test17", "X4", "foo"))	gm.StoreNode("main", constructNode("19", "test18", "X5", "foo"))	return gm, mgs}
 |