package system import ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "os" "strings" "time" sql "github.com/otoolep/rqlite/db" httpd "github.com/otoolep/rqlite/http" "github.com/otoolep/rqlite/store" ) // Node represents a node under test. type Node struct { Addr string Dir string Store *store.Store Service *httpd.Service } // Deprovisions removes all resources associated with the node. func (n *Node) Deprovision() { n.Store.Close() n.Service.Close() os.RemoveAll(n.Dir) } // WaitForLeader blocks for up to 10 seconds until the node detects a leader. func (n *Node) WaitForLeader() error { _, err := n.Store.WaitForLeader(10 * time.Second) return err } // Execute executes a single statement against the node. func (n *Node) Execute(stmt string) (string, error) { j, err := json.Marshal([]string{stmt}) if err != nil { return "", err } stmt = string(j) resp, err := http.Post("http://"+n.Addr+"/db/execute", "application/json", strings.NewReader(stmt)) if err != nil { return "", err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } return string(body), nil } // Query runs a single query against the node. func (n *Node) Query(stmt string) (string, error) { v, _ := url.Parse("http://" + n.Addr + "/db/query") v.RawQuery = url.Values{"q": []string{stmt}}.Encode() resp, err := http.Get(v.String()) if err != nil { return "", err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } return string(body), nil } func mustNewNode(joinAddr string) *Node { node := &Node{ Dir: mustTempDir(), } dbConf := sql.NewConfig() node.Store = store.New(dbConf, node.Dir, "localhost:0") if err := node.Store.Open(joinAddr == ""); err != nil { node.Deprovision() panic(fmt.Sprintf("failed to open store: %s", err.Error())) } node.Service = httpd.New("localhost:0", node.Store, nil) if err := node.Service.Start(); err != nil { node.Deprovision() panic(fmt.Sprintf("failed to start HTTP server: %s", err.Error())) } node.Addr = node.Service.Addr().String() return node } func mustNewLeaderNode() *Node { node := mustNewNode("") if err := node.WaitForLeader(); err != nil { node.Deprovision() panic("node never became leader") } return node } func mustTempDir() string { var err error path, err := ioutil.TempDir("", "rqlilte-system-test-") if err != nil { panic("failed to create temp dir") } return path }