Add more metric tests for value testing (#104)

This commit is contained in:
Rob Parker
2018-06-04 14:56:18 +01:00
committed by GitHub
parent 0f4e79c0a6
commit 2af6953b2b
4 changed files with 153 additions and 66 deletions

View File

@@ -50,7 +50,7 @@ func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
}, },
} }
url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getWebPort(t, cli, ID)) url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getPort(t, cli, ID, 9443))
for { for {
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
req.SetBasicAuth("admin", devAdminPassword) req.SetBasicAuth("admin", devAdminPassword)
@@ -149,7 +149,7 @@ func testREST(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config
}, },
} }
url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getWebPort(t, cli, ID)) url := fmt.Sprintf("https://localhost:%s/ibmmq/rest/v1/admin/installation", getPort(t, cli, ID, 9443))
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
req.SetBasicAuth("admin", devAdminPassword) req.SetBasicAuth("admin", devAdminPassword)
resp, err := httpClient.Do(req) resp, err := httpClient.Do(req)

View File

@@ -564,12 +564,13 @@ func copyFromContainer(t *testing.T, cli *client.Client, id string, file string)
return b return b
} }
func getWebPort(t *testing.T, cli *client.Client, ID string) string { func getPort(t *testing.T, cli *client.Client, ID string, port int) string {
i, err := cli.ContainerInspect(context.Background(), ID) i, err := cli.ContainerInspect(context.Background(), ID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return i.NetworkSettings.Ports["9443/tcp"][0].HostPort portNat := nat.Port(fmt.Sprintf("%d/tcp", port))
return i.NetworkSettings.Ports[portNat][0].HostPort
} }
func countLines(t *testing.T, r io.Reader) int { func countLines(t *testing.T, r io.Reader) int {

View File

@@ -16,6 +16,9 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"net"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
@@ -31,18 +34,19 @@ func TestGoldenPathMetric(t *testing.T) {
} }
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
// hostname := getIPAddress(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned but had none...") t.Error("Expected some metrics to be returned but had none...")
t.Fail()
} }
// Stop the container cleanly // Stop the container cleanly
stopContainer(t, cli, id) stopContainer(t, cli, id)
@@ -57,21 +61,22 @@ func TestMetricNames(t *testing.T) {
} }
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id)
port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call // Call once as mq_prometheus 'ignores' the first call
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned but had none...") t.Error("Expected some metrics to be returned but had none...")
t.Fail()
} }
okMetrics := []string{} // Check all the metrics have approved suffixes
badMetrics := []string{}
for _, metric := range metrics { for _, metric := range metrics {
ok := false ok := false
for _, e := range approvedSuffixes { for _, e := range approvedSuffixes {
@@ -82,11 +87,7 @@ func TestMetricNames(t *testing.T) {
} }
if !ok { if !ok {
t.Logf("Metric '%s' does not have an approved suffix", metric.Key) t.Errorf("Metric '%s' does not have an approved suffix", metric.Key)
badMetrics = append(badMetrics, metric.Key)
t.Fail()
} else {
okMetrics = append(okMetrics, metric.Key)
} }
} }
@@ -103,17 +104,22 @@ func TestMetricLabels(t *testing.T) {
} }
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call // Call once as mq_prometheus 'ignores' the first call
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Error("Expected some metrics to be returned but had none") t.Error("Expected some metrics to be returned but had none")
} }
// Check all the metrics have the required labels
for _, metric := range metrics { for _, metric := range metrics {
found := false found := false
for key := range metric.Labels { for key := range metric.Labels {
@@ -132,6 +138,7 @@ func TestMetricLabels(t *testing.T) {
t.Errorf("Metric '%s' with labels %s does not have one or more required labels - %s", metric.Key, metric.Labels, requiredLabels) t.Errorf("Metric '%s' with labels %s does not have one or more required labels - %s", metric.Key, metric.Labels, requiredLabels)
} }
} }
// Stop the container cleanly // Stop the container cleanly
stopContainer(t, cli, id) stopContainer(t, cli, id)
} }
@@ -144,21 +151,27 @@ func TestRapidFirePrometheus(t *testing.T) {
} }
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
// Rapid fire it then check we're still happy // Rapid fire it then check we're still happy
for i := 0; i < 30; i++ { for i := 0; i < 30; i++ {
getMetrics(t, port) getMetrics(t, port)
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
time.Sleep(11 * time.Second) time.Sleep(11 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Error("Expected some metrics to be returned but had none") t.Error("Expected some metrics to be returned but had none")
} }
// Stop the container cleanly // Stop the container cleanly
stopContainer(t, cli, id) stopContainer(t, cli, id)
} }
@@ -171,21 +184,24 @@ func TestSlowPrometheus(t *testing.T) {
} }
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
// Send a request twice over a long period and check we're still happy // Send a request twice over a long period and check we're still happy
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned but had none") t.Error("Expected some metrics to be returned but had none")
t.Fail()
} }
} }
// Stop the container cleanly // Stop the container cleanly
stopContainer(t, cli, id) stopContainer(t, cli, id)
} }
@@ -199,40 +215,42 @@ func TestContainerRestart(t *testing.T) {
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned before the restart but had none...") t.Fatal("Expected some metrics to be returned before the restart but had none...")
t.FailNow()
} }
// Stop the container cleanly // Stop the container cleanly
stopContainer(t, cli, id) stopContainer(t, cli, id)
// Start the container cleanly // Start the container cleanly
startContainer(t, cli, id) startContainer(t, cli, id)
port = getPort(t, cli, id, defaultMetricPort)
port = getMetricPort(t, cli, id)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics = getMetrics(t, port) metrics = getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned before the restart but had none...") t.Error("Expected some metrics to be returned after the restart but had none...")
t.Fail()
} }
// Stop the container cleanly
stopContainer(t, cli, id)
} }
func TestQMRestart(t *testing.T) { func TestQMRestart(t *testing.T) {
@@ -245,33 +263,31 @@ func TestQMRestart(t *testing.T) {
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort}) id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id) defer cleanContainer(t, cli, id)
port := getMetricPort(t, cli, id) port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up. // Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port) waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port) metrics := getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned before the restart but had none...") t.Fatal("Expected some metrics to be returned before the restart but had none...")
t.FailNow()
} }
// Restart just the QM (to simulate a lost connection) // Restart just the QM (to simulate a lost connection)
t.Log("Stopping queue manager\n") t.Log("Stopping queue manager\n")
rc, out := execContainer(t, cli, id, "mqm", []string{"endmqm", "-w", defaultMetricQMName}) rc, out := execContainer(t, cli, id, "mqm", []string{"endmqm", "-w", defaultMetricQMName})
if rc != 0 { if rc != 0 {
t.Logf("Failed to stop the queue manager. rc=%d, err=%s", rc, out) t.Fatalf("Failed to stop the queue manager. rc=%d, err=%s", rc, out)
t.FailNow()
} }
t.Log("starting queue manager\n") t.Log("starting queue manager\n")
rc, out = execContainer(t, cli, id, "mqm", []string{"strmqm", defaultMetricQMName}) rc, out = execContainer(t, cli, id, "mqm", []string{"strmqm", defaultMetricQMName})
if rc != 0 { if rc != 0 {
t.Logf("Failed to start the queue manager. rc=%d, err=%s", rc, out) t.Fatalf("Failed to start the queue manager. rc=%d, err=%s", rc, out)
t.FailNow()
} }
// Wait for the queue manager to come back up // Wait for the queue manager to come back up
@@ -282,12 +298,12 @@ func TestQMRestart(t *testing.T) {
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics // Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port) getMetrics(t, port)
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics = getMetrics(t, port) metrics = getMetrics(t, port)
if len(metrics) <= 0 { if len(metrics) <= 0 {
t.Log("Expected some metrics to be returned before the restart but had none...") t.Errorf("Expected some metrics to be returned after the restart but had none...")
t.FailNow()
} }
// Stop the container cleanly // Stop the container cleanly
@@ -295,9 +311,97 @@ func TestQMRestart(t *testing.T) {
} }
func TestValidValues(t *testing.T) { func TestValidValues(t *testing.T) {
t.Parallel()
cli, err := client.NewEnvClient()
if err != nil {
t.Fatal(err)
}
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{defaultMetricPort})
defer cleanContainer(t, cli, id)
// hostname := getIPAddress(t, cli, id)
port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port)
time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port)
if len(metrics) <= 0 {
t.Fatal("Expected some metrics to be returned but had none...")
}
// Check that the values for each metric are valid numbers
// can be either int, float or exponential - all these can be parsed by ParseFloat function
for _, e := range metrics {
if _, err = strconv.ParseFloat(e.Value, 64); err != nil {
t.Errorf("Value (%s) for key (%s) is not a valid number", e.Value, e.Key)
}
}
// Stop the container cleanly
stopContainer(t, cli, id)
} }
func TestChangingValues(t *testing.T) { func TestChangingValues(t *testing.T) {
t.Parallel()
cli, err := client.NewEnvClient()
if err != nil {
t.Fatal(err)
}
id := runContainerWithPorts(t, cli, metricsContainerConfig(), []int{1414, defaultMetricPort})
defer cleanContainer(t, cli, id)
// hostname := getIPAddress(t, cli, id)
port := getPort(t, cli, id, defaultMetricPort)
// Now the container is ready we prod the prometheus endpoint until it's up.
waitForMetricReady(t, port)
// Call once as mq_prometheus 'ignores' the first call and will not return any metrics
getMetrics(t, port)
time.Sleep(15 * time.Second)
// Now actually get the metrics (after waiting for some to become available)
metrics := getMetrics(t, port)
if len(metrics) <= 0 {
t.Fatal("Expected some metrics to be returned but had none...")
}
// Check we have no FDC files to start
for _, e := range metrics {
if e.Key == "ibmmq_qmgr_mq_fdc_file_count" {
if e.Value != "0" {
t.Fatalf("Expected %s to have a value of 0 but was %s", e.Key, e.Value)
}
}
}
// Send invalid data to the MQ listener to generate a FDC
listener := fmt.Sprintf("localhost:%s", getPort(t, cli, id, 1414))
conn, err := net.Dial("tcp", listener)
if err != nil {
t.Fatalf("Could not connect to the listener - %v", err)
}
fmt.Fprintf(conn, "THIS WILL GENERATE A FDC!")
conn.Close()
// Now actually get the metrics (after waiting for some to become available)
time.Sleep(15 * time.Second)
metrics = getMetrics(t, port)
if len(metrics) <= 0 {
t.Fatal("Expected some metrics to be returned but had none...")
}
// Check that there is now 1 FDC file
for _, e := range metrics {
if e.Key == "ibmmq_qmgr_mq_fdc_file_count" {
if e.Value != "1" {
t.Fatalf("Expected %s to have a value of 1 but was %s", e.Key, e.Value)
}
}
}
// Stop the container cleanly
stopContainer(t, cli, id)
} }

View File

@@ -17,18 +17,14 @@ package main
import ( import (
"bufio" "bufio"
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
) )
type mqmetric struct { type mqmetric struct {
@@ -42,9 +38,9 @@ const defaultMetricPort = 9157
const defaultMQNamespace = "ibmmq" const defaultMQNamespace = "ibmmq"
const defaultMetricQMName = "qm1" const defaultMetricQMName = "qm1"
func getMetrics(t *testing.T, port int) []mqmetric { func getMetrics(t *testing.T, port string) []mqmetric {
returned := []mqmetric{} returned := []mqmetric{}
urlToUse := fmt.Sprintf("http://localhost:%v%v", port, defaultMetricURL) urlToUse := fmt.Sprintf("http://localhost:%s%s", port, defaultMetricURL)
resp, err := http.Get(urlToUse) resp, err := http.Get(urlToUse)
if err != nil { if err != nil {
t.Fatalf("Error from HTTP GET for metrics: %v", err) t.Fatalf("Error from HTTP GET for metrics: %v", err)
@@ -135,10 +131,10 @@ func convertMetricLineToMetric(input string) (string, string, map[string]string,
return key, value, labelMap, nil return key, value, labelMap, nil
} }
func waitForMetricReady(t *testing.T, port int) { func waitForMetricReady(t *testing.T, port string) {
timeout := 12 // 12 * 5 = 1 minute timeout := 12 // 12 * 5 = 1 minute
for i := 0; i < timeout; i++ { for i := 0; i < timeout; i++ {
urlToUse := fmt.Sprintf("http://localhost:%v", port) urlToUse := fmt.Sprintf("http://localhost:%s", port)
resp, err := http.Get(urlToUse) resp, err := http.Get(urlToUse)
if err == nil { if err == nil {
resp.Body.Close() resp.Body.Close()
@@ -150,20 +146,6 @@ func waitForMetricReady(t *testing.T, port int) {
t.Fatalf("Metric endpoint failed to startup in timely manner") t.Fatalf("Metric endpoint failed to startup in timely manner")
} }
func getMetricPort(t *testing.T, cli *client.Client, ID string) int {
i, err := cli.ContainerInspect(context.Background(), ID)
if err != nil {
t.Fatal(err)
}
port := nat.Port(fmt.Sprintf("%v/tcp", defaultMetricPort))
portString := i.NetworkSettings.Ports[port][0].HostPort
p, err := strconv.Atoi(portString)
if err != nil {
t.Fatal(err)
}
return p
}
func metricsContainerConfig() *container.Config { func metricsContainerConfig() *container.Config {
return &container.Config{ return &container.Config{
Env: []string{ Env: []string{