func Test_ServerSingleGraphiteIntegration_NoDatabase(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}
	nNodes := 1
	basePort := 8490
	testName := "graphite integration"
	dir := tempfile()
	now := time.Now().UTC().Round(time.Millisecond)
	c := main.NewConfig()
	g := main.Graphite{
		Enabled:  true,
		Port:     2103,
		Protocol: "TCP",
	}
	c.Graphites = append(c.Graphites, g)
	c.Logging.WriteTracing = true

	t.Logf("Graphite Connection String: %s\n", g.ConnectionString(c.BindAddress))
	nodes := createCombinedNodeCluster(t, testName, dir, nNodes, basePort, c)

	// Connect to the graphite endpoint we just spun up
	conn, err := net.Dial("tcp", g.ConnectionString(c.BindAddress))
	if err != nil {
		t.Fatal(err)
		return
	}

	// Need to wait for the database to be created
	expected := `{"results":[{"series":[{"columns":["name"],"values":[["graphite"]]}]}]}`
	got, ok := queryAndWait(t, nodes, "graphite", `show databases`, expected, 2*time.Second)
	if !ok {
		t.Errorf(`Test "%s" failed, expected: %s, got: %s`, testName, expected, got)
	}

	// Need to wait for the database to get a default retention policy
	expected = `{"results":[{"series":[{"columns":["name","duration","replicaN","default"],"values":[["default","0",1,true]]}]}]}`
	got, ok = queryAndWait(t, nodes, "graphite", `show retention policies graphite`, expected, 2*time.Second)
	if !ok {
		t.Errorf(`Test "%s" failed, expected: %s, got: %s`, testName, expected, got)
	}

	t.Log("Writing data")
	data := []byte(`cpu 23.456 `)
	data = append(data, []byte(fmt.Sprintf("%d", now.UnixNano()/1000000))...)
	data = append(data, '\n')
	_, err = conn.Write(data)
	conn.Close()
	if err != nil {
		t.Fatal(err)
		return
	}

	// Wait for data to show up
	expected = fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","cpu"],"values":[["%s",23.456]]}]}]}`, now.Format(time.RFC3339Nano))
	got, ok = queryAndWait(t, nodes, "graphite", `select * from "graphite"."default".cpu`, expected, 2*time.Second)
	if !ok {
		t.Errorf(`Test "%s" failed, expected: %s, got: %s`, testName, expected, got)
	}
}
func Test_ServerSingleGraphiteIntegration(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}
	nNodes := 1
	basePort := 8390
	testName := "graphite integration"
	dir := tempfile()
	now := time.Now().UTC().Round(time.Millisecond)
	c := main.NewConfig()
	g := main.Graphite{
		Enabled:  true,
		Database: "graphite",
		Protocol: "TCP",
	}
	c.Graphites = append(c.Graphites, g)

	t.Logf("Graphite Connection String: %s\n", g.ConnectionString(c.BindAddress))
	nodes := createCombinedNodeCluster(t, testName, dir, nNodes, basePort, c)

	createDatabase(t, testName, nodes, "graphite")
	createRetentionPolicy(t, testName, nodes, "graphite", "raw")

	// Connect to the graphite endpoint we just spun up
	conn, err := net.Dial("tcp", g.ConnectionString(c.BindAddress))
	if err != nil {
		t.Fatal(err)
		return
	}

	t.Log("Writing data")
	data := []byte(`cpu 23.456 `)
	data = append(data, []byte(fmt.Sprintf("%d", now.UnixNano()/1000000))...)
	data = append(data, '\n')
	_, err = conn.Write(data)
	conn.Close()
	if err != nil {
		t.Fatal(err)
		return
	}

	expected := fmt.Sprintf(`{"results":[{"series":[{"name":"cpu","columns":["time","cpu"],"values":[["%s",23.456]]}]}]}`, now.Format(time.RFC3339Nano))

	// query and wait for results
	got, ok := queryAndWait(t, nodes, "graphite", `select * from "graphite"."raw".cpu`, expected, 2*time.Second)
	if !ok {
		t.Errorf(`Test "%s" failed, expected: %s, got: %s`, testName, expected, got)
	}
}
// createCombinedNodeCluster creates a cluster of nServers nodes, each of which
// runs as both a Broker and Data node. If any part cluster creation fails,
// the testing is marked as failed.
//
// This function returns a slice of nodes, the first of which will be the leader.
func createCombinedNodeCluster(t *testing.T, testName, tmpDir string, nNodes, basePort int, baseConfig *main.Config) Cluster {
	t.Logf("Creating cluster of %d nodes for test %s", nNodes, testName)
	if nNodes < 1 {
		t.Fatalf("Test %s: asked to create nonsense cluster", testName)
	}

	nodes := make([]*Node, 0)

	tmpBrokerDir := filepath.Join(tmpDir, "broker-integration-test")
	tmpDataDir := filepath.Join(tmpDir, "data-integration-test")
	t.Logf("Test %s: using tmp directory %q for brokers\n", testName, tmpBrokerDir)
	t.Logf("Test %s: using tmp directory %q for data nodes\n", testName, tmpDataDir)
	// Sometimes if a test fails, it's because of a log.Fatal() in the program.
	// This prevents the defer from cleaning up directories.
	// To be safe, nuke them always before starting
	_ = os.RemoveAll(tmpBrokerDir)
	_ = os.RemoveAll(tmpDataDir)

	// Create the first node, special case.
	c := baseConfig
	if c == nil {
		c = main.NewConfig()
	}
	c.Broker.Dir = filepath.Join(tmpBrokerDir, strconv.Itoa(basePort))
	c.Data.Dir = filepath.Join(tmpDataDir, strconv.Itoa(basePort))
	c.Broker.Port = basePort
	c.Data.Port = basePort
	c.Admin.Enabled = false
	c.ReportingDisabled = true

	b, s := main.Run(c, "", "x.x", os.Stderr)
	if b == nil {
		t.Fatalf("Test %s: failed to create broker on port %d", testName, basePort)
	}
	if s == nil {
		t.Fatalf("Test %s: failed to create leader data node on port %d", testName, basePort)
	}
	nodes = append(nodes, &Node{
		broker: b,
		server: s,
		url:    &url.URL{Scheme: "http", Host: "localhost:" + strconv.Itoa(basePort)},
		leader: true,
	})

	// Create subsequent nodes, which join to first node.
	for i := 1; i < nNodes; i++ {
		nextPort := basePort + i
		c.Broker.Dir = filepath.Join(tmpBrokerDir, strconv.Itoa(nextPort))
		c.Data.Dir = filepath.Join(tmpDataDir, strconv.Itoa(nextPort))
		c.Broker.Port = nextPort
		c.Data.Port = nextPort

		b, s := main.Run(c, "http://localhost:"+strconv.Itoa(basePort), "x.x", os.Stderr)
		if b == nil {
			t.Fatalf("Test %s: failed to create following broker on port %d", testName, basePort)
		}
		if s == nil {
			t.Fatalf("Test %s: failed to create following data node on port %d", testName, basePort)
		}

		nodes = append(nodes, &Node{
			broker: b,
			server: s,
			url:    &url.URL{Scheme: "http", Host: "localhost:" + strconv.Itoa(nextPort)},
		})
	}

	return nodes
}