summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHorus_Arch2015-02-23 12:13:32 +0100
committerHorus_Arch2015-02-23 12:13:32 +0100
commit70d080b69a1bce3125d8d0b83e23775880241763 (patch)
tree6fac80f9291e361045098b2ce9eb0839652e6b42
parent00b28812fb5ab68156ead5b45b66740a4d5ca688 (diff)
downloadstatuspage-70d080b69a1bce3125d8d0b83e23775880241763.tar.gz
Refactor and more unit tests.
-rw-r--r--app/Makefile25
-rw-r--r--app/cache.go33
-rw-r--r--app/cache_test.go54
-rw-r--r--app/fetch.go65
-rw-r--r--app/fetch_test.go60
-rw-r--r--app/handler.go9
-rw-r--r--app/handler_test.go35
-rw-r--r--app/jobs.go10
-rw-r--r--app/test.go2
-rw-r--r--app/utilities.go18
-rw-r--r--app/utilities_test.go68
11 files changed, 294 insertions, 85 deletions
diff --git a/app/Makefile b/app/Makefile
index c847c75..8624cd8 100644
--- a/app/Makefile
+++ b/app/Makefile
@@ -22,6 +22,18 @@ ifndef STATUS_HTTP_PORT
export STATUS_HTTP_PORT:=8080
endif
+ifdef TEST_RACE
+ RACE:=-race
+else
+ RACE:=
+endif
+
+ifdef TEST_VERBOSE
+ VERBOSE:=-v
+else
+ VERBOSE:=
+endif
+
IMPORT_FILE:=./import.go
APP:=statuspage
@@ -76,10 +88,17 @@ pack:
(echo "Run \"make build\" first." && exit 1)
test:
- go test -v -race -tags general
+ go test $(RACE) $(VERBOSE) -tags general
test_all: import
- go test -v -race -tags all
+ go test $(RACE) $(VERBOSE) -v -tags all
test_dependencies: import
- go test -v -race -tags dep
+ go test $(RACE) $(VERBOSE) -tags dep
+
+benchmark:
+ go test $(VERBOSE) -bench=".*" -tags general
+
+benchmark_dependencies: import
+ export DB_STATUS_LOG=false
+ go test $(VERBOSE) -bench=".*" -tags dep
diff --git a/app/cache.go b/app/cache.go
new file mode 100644
index 0000000..f75f317
--- /dev/null
+++ b/app/cache.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "encoding/json"
+ "github.com/garyburd/redigo/redis"
+ "log"
+)
+
+const (
+ cache_prefix = "status_"
+)
+
+func CacheHosts(prefix string, h []Host) error {
+ c := pool.Get()
+ js, err := json.Marshal(h)
+ if err != nil {
+ log.Println("Serizaling to JSON failed.")
+ return err
+ }
+ c.Do("SET", prefix, js)
+ return nil
+}
+
+func GetCache(key string) (string, error) {
+ c := pool.Get()
+ return redis.String(c.Do("GET", key))
+}
+
+func DelCache(key string) error {
+ c := pool.Get()
+ _, err := c.Do("DEL", key)
+ return err
+}
diff --git a/app/cache_test.go b/app/cache_test.go
new file mode 100644
index 0000000..a44d2e1
--- /dev/null
+++ b/app/cache_test.go
@@ -0,0 +1,54 @@
+// +build all dep
+
+package main
+
+import (
+ "testing"
+)
+
+func TestCache(t *testing.T) {
+ h := []Host{}
+
+ err := CacheHosts("_test", h)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ resp, err := GetCache("_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if resp != "[]" {
+ t.Fatal("Expected '[]' as result.")
+ }
+
+ if err = DelCache("_test"); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func BenchmarkCacheHosts(b *testing.B) {
+ b.StopTimer()
+ h := []Host{}
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ CacheHosts("_test", h)
+ }
+}
+
+func BenchmarkGetCache(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ GetCache("_test")
+ }
+}
+
+func BenchmarkDelCache(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ DelCache("_test")
+ b.StopTimer()
+ h := []Host{}
+ CacheHosts("_test", h)
+ b.StartTimer()
+ }
+}
diff --git a/app/fetch.go b/app/fetch.go
index a3d3ae7..3ddd97b 100644
--- a/app/fetch.go
+++ b/app/fetch.go
@@ -1,85 +1,38 @@
package main
import (
- "encoding/json"
"fmt"
- // "strconv"
- // "time"
- "log"
-)
-
-func jobRun() {
- c := c
- c.AddFunc("@every 10s", healthCheck)
- c.Start()
- jobs := c.Entries()
-
- for _, i := range jobs {
- fmt.Printf("Job: %v, Schedule: %v; Next %v; Prev %v \n", i.Job, i.Schedule, i.Next, i.Prev)
- }
-}
-
-const (
- cache_prefix = "status_"
)
func healthCheck() {
h := []Host{}
- db := Db
- //db.Where("monitored = ?", true).Find(&h)
- db.Find(&h)
+ Db.Find(&h)
+ h = CheckPage(h)
+ CacheHosts(cache_prefix+"database", h)
+ for k, _ := range h {
+ Db.Debug().Save(&h[k])
+ }
+}
- c := pool.Get()
- defer c.Close()
+func CheckPage(h []Host) []Host {
for k, v := range h {
if !h[k].Monitored {
continue
}
-
if resp, _, err := HttpGet(v.Url); err != nil {
- //fmt.Println(err)
-
h[k].Status = "Error"
h[k].StatusCode = 0
h[k].Success = false
h[k].Monitored = false
h[k].Reason = fmt.Sprintf("%v", err)
- Db.Debug().Save(&h[k])
-
} else {
- // fmt.Println("Health check: Okay! ", resp.Status)
-
h[k].Status = resp.Status
h[k].StatusCode = int64(resp.StatusCode)
h[k].Success = true
h[k].Reason = ""
- Db.Debug().Save(&h[k])
}
-
- // save struct in redis as serialized json
- // TODO
- /*
- j, err := json.Marshal(h[k])
- if err != nil {
- log.Println("Error: ", err)
- continue
- }
- c.Do("SET", cache_prefix+strconv.Itoa(k), j)
- */
-
- //c.Do("SET", cache_prefix+strconv.Itoa(k), j)
- //c.Do("SET", k, j)
-
- // fmt.Printf("Id: %v, Url: %v \n", v.Id, v.Url)
-
}
- js, err := json.Marshal(h)
-
- if err != nil {
- log.Fatal(err)
- } else {
- c.Do("SET", cache_prefix+"database", js)
- }
+ return h
}
diff --git a/app/fetch_test.go b/app/fetch_test.go
new file mode 100644
index 0000000..b71a3fe
--- /dev/null
+++ b/app/fetch_test.go
@@ -0,0 +1,60 @@
+// +build all general
+
+package main
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestCheckPage(t *testing.T) {
+ answer := ""
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html")
+ w.WriteHeader(0)
+ fmt.Fprintln(w, answer)
+ }))
+ defer ts.Close()
+
+ fakeUrlSuccess := ts.URL
+
+ h := []Host{}
+ host := Host{
+ Url: fakeUrlSuccess,
+ Monitored: true,
+ }
+ h = append(h, host)
+ test := CheckPage(h)
+ if test == nil {
+ t.Fatal("Expected slice to be not nil.")
+ }
+ if test[0].StatusCode != 0 {
+ t.Errorf("Expected StatusCode 0 instead of %v.\n", test[0].StatusCode)
+ t.Logf("Failed test for %v .\n", test[0].Url)
+ } else {
+ t.Logf("Passed test for %v.\n", test[0].Url)
+ }
+
+ ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html")
+ w.WriteHeader(200)
+ fmt.Fprintln(w, answer)
+ }))
+ defer ts.Close()
+
+ h2 := []Host{}
+ host2 := Host{
+ Url: ts2.URL,
+ Monitored: true,
+ }
+ h2 = append(h2, host2)
+ test2 := CheckPage(h2)
+ if test2[0].StatusCode != 200 {
+ t.Errorf("Expected StatusCode 200 instead of %v.\n", test2[0].StatusCode)
+ t.Logf("Failed test for %v .\n", test2[0].Url)
+ } else {
+ t.Logf("Passed test for %v .\n", test2[0].Url)
+ }
+}
diff --git a/app/handler.go b/app/handler.go
index 9a3352f..510514a 100644
--- a/app/handler.go
+++ b/app/handler.go
@@ -1,17 +1,14 @@
package main
import (
- "fmt"
- // "html/template"
"encoding/json"
+ "fmt"
"github.com/garyburd/redigo/redis"
"log"
"net/http"
)
func IndexHandler(w http.ResponseWriter, r *http.Request) {
- log.Println("Print IndexHandler")
-
hosts := []Host{}
c := pool.Get()
@@ -23,10 +20,12 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
log.Println("Error JSON decoding: ", err)
Db.Find(&hosts)
+ CacheHosts(cache_prefix+"database", hosts)
}
} else {
log.Println("Redis: ", err)
Db.Find(&hosts)
+ CacheHosts(cache_prefix+"database", hosts)
}
index := mainTempl.Lookup("index.html")
@@ -40,13 +39,11 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
func RegisterHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Processing registration!")
fmt.Fprintf(w, "Processing registration! \n")
- // w.Write()
}
func PrintRegisterHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Printing register etc! \n")
- // w.Write()
}
func PrintNewJobHandler(w http.ResponseWriter, r *http.Request) {
diff --git a/app/handler_test.go b/app/handler_test.go
new file mode 100644
index 0000000..67692b0
--- /dev/null
+++ b/app/handler_test.go
@@ -0,0 +1,35 @@
+// +build all dep
+
+package main
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestIndexHandler(t *testing.T) {
+ request, err := http.NewRequest("GET", "/", nil)
+ if err != nil {
+ t.Log("Error creating new http request. ", err)
+ }
+ response := httptest.NewRecorder()
+
+ IndexHandler(response, request)
+
+ if response.Code != 200 {
+ t.Log(response.Code)
+ t.Fatal("Expected 200 as status code.")
+ }
+}
+
+func BenchmarkIndexHandler(b *testing.B) {
+ b.StopTimer()
+ request, _ := http.NewRequest("GET", "/", nil)
+ response := httptest.NewRecorder()
+
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ IndexHandler(response, request)
+ }
+}
diff --git a/app/jobs.go b/app/jobs.go
new file mode 100644
index 0000000..0cbfc47
--- /dev/null
+++ b/app/jobs.go
@@ -0,0 +1,10 @@
+package main
+
+func jobRun() {
+ c.AddFunc("@every 10s", healthCheck)
+ c.Start()
+}
+
+func jobStop() {
+ c.Stop()
+}
diff --git a/app/test.go b/app/test.go
index 200c272..3181eb4 100644
--- a/app/test.go
+++ b/app/test.go
@@ -5,7 +5,7 @@ import (
)
func insertHost() {
- h := Host{Url: "https://mx.iamfabulous.de/", Monitored: true, Private: false}
+ h := Host{Url: "http://www.iamfabulous.de/", Monitored: true, Private: false}
Db.Create(&h)
h = Host{Url: "https://iamfabulousadsfadfdsf.de/", Monitored: true, Private: false}
Db.Create(&h)
diff --git a/app/utilities.go b/app/utilities.go
index a3c3617..b34efd8 100644
--- a/app/utilities.go
+++ b/app/utilities.go
@@ -17,22 +17,7 @@ import (
"time"
)
-/*
-type errorString struct {
- s string
-}
-
-func (e *errorString) Error() string {
- return e.s
-}
-
-// New returns an error that formats as the given text.
-func New(text string) error {
- return &errorString{text}
-}
-*/
-
-// Returns headers as map and the content of a webpage as string
+// Returns the response from a GET request plus the headers as map and the content as string
func HttpGet(url string) (*http.Response, string, error) {
r, err := http.Get(url)
if err != nil {
@@ -59,6 +44,7 @@ func Md5Hash(content string) string {
// Creates a random string
func RandomKey() string {
+ rand.Seed(time.Now().UTC().UnixNano())
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
key := make([]rune, 40)
for i := range key {
diff --git a/app/utilities_test.go b/app/utilities_test.go
index 5405309..22f1f5e 100644
--- a/app/utilities_test.go
+++ b/app/utilities_test.go
@@ -3,9 +3,37 @@
package main
import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "strings"
"testing"
)
+func TestHttpGet(t *testing.T) {
+ answer := "Fake webpage here."
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html")
+ fmt.Fprintln(w, answer)
+ }))
+ defer ts.Close()
+
+ fakeUrl := ts.URL
+
+ resp, content, err := HttpGet(fakeUrl)
+ if err != nil {
+ t.Fatal("Error getting web page.")
+ }
+ if resp.StatusCode != 200 {
+ t.Fatal("Expecting 200 as status code.")
+ }
+ if strings.TrimSpace(content) != answer {
+ t.Log("We got this: ", content)
+ t.Log("We expected this: ", answer)
+ t.Fatal("Webpage returned wrong answer.")
+ }
+}
+
func TestMd5Hash(t *testing.T) {
hash := "f9d08276bc85d30d578e8883f3c7e843"
testHash := Md5Hash("md5hash")
@@ -16,9 +44,19 @@ func TestMd5Hash(t *testing.T) {
}
func TestRandomKey(t *testing.T) {
- key := RandomKey()
- if len(key) != 40 {
- t.Fatal("Expected a key with length of 40. Got %s.", key)
+ m := map[string]bool{}
+ var key string
+ for i := 0; i < 100; i++ {
+ key = RandomKey()
+ t.Log(key)
+ if m[key] {
+ t.Fatal("Key not random.")
+ } else {
+ m[key] = true
+ }
+ if len(key) != 40 {
+ t.Fatal("Expected a key with length of 40. Got %s.", key)
+ }
}
}
@@ -42,3 +80,27 @@ func TestPassword(t *testing.T) {
t.Fatal("Verifying empty password.")
}
}
+
+func BenchmarkMd5Hash(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Md5Hash("md5hash")
+ }
+}
+
+func BenchmarkRandomKey(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ RandomKey()
+ }
+}
+
+func BenchmarkHashPassword(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ HashPassword("password")
+ }
+}
+
+func BenchmarkVerifyPassword(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ VerifyPassword("password", "$2a$10$OnsbG0Obaz2af3UkoQ9Jaeky3zfRi.0ZHCJC8DlWnbqbpaXEhWqYe")
+ }
+}