diff options
| author | Horus_Arch | 2015-02-23 12:13:32 +0100 |
|---|---|---|
| committer | Horus_Arch | 2015-02-23 12:13:32 +0100 |
| commit | 70d080b69a1bce3125d8d0b83e23775880241763 (patch) | |
| tree | 6fac80f9291e361045098b2ce9eb0839652e6b42 | |
| parent | 00b28812fb5ab68156ead5b45b66740a4d5ca688 (diff) | |
| download | statuspage-70d080b69a1bce3125d8d0b83e23775880241763.tar.gz | |
Refactor and more unit tests.
| -rw-r--r-- | app/Makefile | 25 | ||||
| -rw-r--r-- | app/cache.go | 33 | ||||
| -rw-r--r-- | app/cache_test.go | 54 | ||||
| -rw-r--r-- | app/fetch.go | 65 | ||||
| -rw-r--r-- | app/fetch_test.go | 60 | ||||
| -rw-r--r-- | app/handler.go | 9 | ||||
| -rw-r--r-- | app/handler_test.go | 35 | ||||
| -rw-r--r-- | app/jobs.go | 10 | ||||
| -rw-r--r-- | app/test.go | 2 | ||||
| -rw-r--r-- | app/utilities.go | 18 | ||||
| -rw-r--r-- | app/utilities_test.go | 68 |
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") + } +} |
