add unit tests to alerts, values, and route to increase test coverage (#158)

Signed-off-by: tariqibrahim <tariq.ibrahim@microsoft.com>
diff --git a/model/alert_test.go b/model/alert_test.go
index 9692bca..e4c93a3 100644
--- a/model/alert_test.go
+++ b/model/alert_test.go
@@ -14,6 +14,8 @@
 package model
 
 import (
+	"fmt"
+	"sort"
 	"strings"
 	"testing"
 	"time"
@@ -116,3 +118,160 @@
 		}
 	}
 }
+
+func TestAlert(t *testing.T) {
+	// Verifying that an alert with no EndsAt field is unresolved and has firing status.
+	alert := &Alert{
+		Labels:   LabelSet{"foo": "bar", "lorem": "ipsum"},
+		StartsAt: time.Now(),
+	}
+
+	actual := fmt.Sprint(alert)
+	expected := "[d181d0f][active]"
+
+	if actual != expected {
+		t.Errorf("expected %s, but got %s", expected, actual)
+	}
+
+	actualStatus := string(alert.Status())
+	expectedStatus := "firing"
+
+	if actualStatus != expectedStatus {
+		t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus)
+	}
+
+	// Verifying that an alert with an EndsAt time before the current time is resolved and has resolved status.
+	ts := time.Now()
+	ts1 := ts.Add(-2 * time.Minute)
+	ts2 := ts.Add(-1 * time.Minute)
+	alert = &Alert{
+		Labels:   LabelSet{"foo": "bar", "lorem": "ipsum"},
+		StartsAt: ts1,
+		EndsAt:   ts2,
+	}
+
+	actual = fmt.Sprint(alert)
+	expected = "[d181d0f][resolved]"
+
+	if actual != expected {
+		t.Errorf("expected %s, but got %s", expected, actual)
+	}
+
+	actualStatus = string(alert.Status())
+	expectedStatus = "resolved"
+
+	if actualStatus != expectedStatus {
+		t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus)
+	}
+}
+
+func TestSortAlerts(t *testing.T) {
+	ts := time.Now()
+	alerts := Alerts{
+		{
+			Labels: LabelSet{
+				"alertname": "InternalError",
+				"dev":       "sda3",
+			},
+			StartsAt: ts.Add(-6 * time.Minute),
+			EndsAt:   ts.Add(-3 * time.Minute),
+		},
+		{
+			Labels: LabelSet{
+				"alertname": "DiskFull",
+				"dev":       "sda1",
+			},
+			StartsAt: ts.Add(-5 * time.Minute),
+			EndsAt:   ts.Add(-4 * time.Minute),
+		},
+		{
+			Labels: LabelSet{
+				"alertname": "OutOfMemory",
+				"dev":       "sda1",
+			},
+			StartsAt: ts.Add(-2 * time.Minute),
+			EndsAt:   ts.Add(-1 * time.Minute),
+		},
+		{
+			Labels: LabelSet{
+				"alertname": "DiskFull",
+				"dev":       "sda2",
+			},
+			StartsAt: ts.Add(-2 * time.Minute),
+			EndsAt:   ts.Add(-3 * time.Minute),
+		},
+		{
+			Labels: LabelSet{
+				"alertname": "OutOfMemory",
+				"dev":       "sda2",
+			},
+			StartsAt: ts.Add(-5 * time.Minute),
+			EndsAt:   ts.Add(-2 * time.Minute),
+		},
+	}
+
+	sort.Sort(alerts)
+
+	expected := []string{
+		"DiskFull[5ffe595][resolved]",
+		"InternalError[09cfd46][resolved]",
+		"OutOfMemory[d43a602][resolved]",
+		"DiskFull[5ff4595][resolved]",
+		"OutOfMemory[d444602][resolved]",
+	}
+
+	for i := range alerts {
+		if alerts[i].String() != expected[i] {
+			t.Errorf("expected alert %s at index %d, but got %s", expected[i], i, alerts[i].String())
+		}
+	}
+}
+
+func TestAlertsStatus(t *testing.T) {
+	firingAlerts := Alerts{
+		{
+			Labels: LabelSet{
+				"foo": "bar",
+			},
+			StartsAt: time.Now(),
+		},
+		{
+			Labels: LabelSet{
+				"bar": "baz",
+			},
+			StartsAt: time.Now(),
+		},
+	}
+
+	actualStatus := firingAlerts.Status()
+	expectedStatus := AlertFiring
+
+	if actualStatus != expectedStatus {
+		t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
+	}
+
+	ts := time.Now()
+	resolvedAlerts := Alerts{
+		{
+			Labels: LabelSet{
+				"foo": "bar",
+			},
+			StartsAt: ts.Add(-1 * time.Minute),
+			EndsAt:   ts,
+		},
+		{
+			Labels: LabelSet{
+				"bar": "baz",
+			},
+			StartsAt: ts.Add(-1 * time.Minute),
+			EndsAt:   ts,
+		},
+	}
+
+	actualStatus = resolvedAlerts.Status()
+	expectedStatus = AlertResolved
+
+	if actualStatus != expectedStatus {
+		t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
+	}
+}
diff --git a/model/value_test.go b/model/value_test.go
index b97dcf8..7936a06 100644
--- a/model/value_test.go
+++ b/model/value_test.go
@@ -402,7 +402,7 @@
 			Metric: Metric{
 				MetricNameLabel: "B",
 			},
-			Timestamp: 1,
+			Timestamp: 3,
 		},
 		&Sample{
 			Metric: Metric{
@@ -410,6 +410,12 @@
 			},
 			Timestamp: 2,
 		},
+		&Sample{
+			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 1,
+		},
 	}
 
 	expected := Vector{
@@ -439,6 +445,12 @@
 		},
 		&Sample{
 			Metric: Metric{
+				MetricNameLabel: "B",
+			},
+			Timestamp: 3,
+		},
+		&Sample{
+			Metric: Metric{
 				MetricNameLabel: "C",
 			},
 			Timestamp: 1,
diff --git a/route/route_test.go b/route/route_test.go
index d491cad..127974c 100644
--- a/route/route_test.go
+++ b/route/route_test.go
@@ -43,6 +43,43 @@
 	router.ServeHTTP(nil, r)
 }
 
+func TestContextWithValue(t *testing.T) {
+	router := New()
+	router.Get("/test/:foo/", func(w http.ResponseWriter, r *http.Request) {
+		want := "bar"
+		got := Param(r.Context(), "foo")
+		if want != got {
+			t.Fatalf("Unexpected context value: want %q, got %q", want, got)
+		}
+		want = "ipsum"
+		got = Param(r.Context(), "lorem")
+		if want != got {
+			t.Fatalf("Unexpected context value: want %q, got %q", want, got)
+		}
+		want = "sit"
+		got = Param(r.Context(), "dolor")
+		if want != got {
+			t.Fatalf("Unexpected context value: want %q, got %q", want, got)
+		}
+	})
+
+	r, err := http.NewRequest("GET", "http://localhost:9090/test/bar/", nil)
+	if err != nil {
+		t.Fatalf("Error building test request: %s", err)
+	}
+	params := map[string]string{
+		"lorem": "ipsum",
+		"dolor": "sit",
+	}
+
+	ctx := r.Context()
+	for p, v := range params {
+		ctx = WithParam(ctx, p, v)
+	}
+	r = r.WithContext(ctx)
+	router.ServeHTTP(nil, r)
+}
+
 func TestInstrumentation(t *testing.T) {
 	var got string
 	cases := []struct {