diff --git a/kadai4/en-ken/kadai4/export_test.go b/kadai4/en-ken/kadai4/export_test.go new file mode 100644 index 0000000..f3e1aff --- /dev/null +++ b/kadai4/en-ken/kadai4/export_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "time" +) + +var GetFortune = getFortune +var Handler = handler + +func SetNow(n func() time.Time) { + now = n +} + +func SetFortunes(f []string) { + fortunes = f +} + +func SetNewEncoder(n NewEncoder) { + newEncoder = n +} diff --git a/kadai4/en-ken/kadai4/fortune.go b/kadai4/en-ken/kadai4/fortune.go new file mode 100644 index 0000000..7eebd47 --- /dev/null +++ b/kadai4/en-ken/kadai4/fortune.go @@ -0,0 +1,29 @@ +package main + +import ( + "math/rand" + "time" +) + +// For testing +var now = time.Now +var fortunes []string + +func init() { + rand.Seed(time.Now().UnixNano()) + fortunes = []string{"大吉", "吉", "中吉", "小吉", "末吉", "凶", "大凶"} +} + +func getFortune() string { + i := rand.Int() % len(fortunes) + f := fortunes[i] + + t := now() + if t.Month() == 1 { + if t.Day() >= 1 && t.Day() <= 3 { + f = "大吉" + } + } + + return f +} diff --git a/kadai4/en-ken/kadai4/fortune_test.go b/kadai4/en-ken/kadai4/fortune_test.go new file mode 100644 index 0000000..56b80f1 --- /dev/null +++ b/kadai4/en-ken/kadai4/fortune_test.go @@ -0,0 +1,64 @@ +package main_test + +import ( + "fmt" + "testing" + "time" + + main "github.com/gopherdojo/dojo6/kadai4/en-ken/kadai4" +) + +func TestGetLuck(t *testing.T) { + + cases := []struct { + now time.Time + expected string + }{ + { + now: time.Date(2018, time.December, 31, 0, 0, 0, 0, time.Local), + expected: "凶", + }, + { + now: time.Date(2018, time.December, 31, 23, 59, 59, 999, time.Local), + expected: "凶", + }, + { + now: time.Date(2019, time.January, 1, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, + { + now: time.Date(2019, time.January, 2, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, + { + now: time.Date(2019, time.January, 3, 0, 0, 0, 0, time.Local), + expected: "大吉", + }, + { + now: time.Date(2018, time.January, 3, 23, 59, 59, 999, time.Local), + expected: "大吉", + }, + { + now: time.Date(2019, time.January, 4, 0, 0, 0, 0, time.Local), + expected: "凶", + }, + } + + main.SetFortunes([]string{"凶", "凶", "凶"}) + + for i, c := range cases { + c := c + t.Run( + fmt.Sprintf("case[%v]", i), + func(t *testing.T) { + main.SetNow(func() time.Time { + return c.now + }) + + if actual := main.GetFortune(); actual != c.expected { + t.Errorf("actual:%v, expected:%v\n", actual, c.expected) + } + }) + } + +} diff --git a/kadai4/en-ken/kadai4/main.go b/kadai4/en-ken/kadai4/main.go new file mode 100644 index 0000000..dd31146 --- /dev/null +++ b/kadai4/en-ken/kadai4/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "encoding/json" + "io" + "net/http" +) + +// Encoder is I/F to json.Encoder +type Encoder interface { + Encode(v interface{}) error +} + +// NewEncoder is I/F to json.NewEncoder +type NewEncoder func(w io.Writer) Encoder + +var newEncoder NewEncoder + +func init() { + // For testing + newEncoder = func(w io.Writer) Encoder { + return json.NewEncoder(w) + } +} + +func main() { + http.HandleFunc("/", handler) + http.ListenAndServe(":8080", nil) +} + +func handler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "applicaiton/json; charset=utf-8") + + enc := newEncoder(w) + + resp := &struct { + Fortune string `json:"fortune"` + }{ + Fortune: getFortune(), + } + + if err := enc.Encode(resp); err != nil { + http.Error(w, "Server error", http.StatusInternalServerError) + } +} diff --git a/kadai4/en-ken/kadai4/main_test.go b/kadai4/en-ken/kadai4/main_test.go new file mode 100644 index 0000000..1b970bb --- /dev/null +++ b/kadai4/en-ken/kadai4/main_test.go @@ -0,0 +1,79 @@ +package main_test + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "testing" + + main "github.com/gopherdojo/dojo6/kadai4/en-ken/kadai4" +) + +type data struct { + Fortune string `json:"fortune"` +} + +func TestServer(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(main.Handler)) + defer ts.Close() + + res, err := http.Get(ts.URL) + if err != nil { + t.Errorf("Response error:%v", err) + } + + var d data + if err = json.NewDecoder(res.Body).Decode(&d); err != nil { + t.Errorf("Data format error:%v", err) + } +} + +type EncoderMock struct { +} + +func NewEncoderMock(w io.Writer) main.Encoder { + return &EncoderMock{} +} + +func (enc *EncoderMock) Encode(v interface{}) error { + return fmt.Errorf("Internal server error") +} + +func TestServerInternalServerError(t *testing.T) { + main.SetNewEncoder(NewEncoderMock) + defer main.SetNewEncoder(main.NewEncoder(func(w io.Writer) main.Encoder { + return json.NewEncoder(w) + })) + + ts := httptest.NewServer(http.HandlerFunc(main.Handler)) + defer ts.Close() + + res, _ := http.Get(ts.URL) + if res.StatusCode != 500 { + t.Errorf("Response code error:%v", res.StatusCode) + } + +} + +func TestHandler(t *testing.T) { + r := httptest.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + main.SetFortunes([]string{"大凶"}) + + main.Handler(w, r) + + if w.Code != 200 { + t.Errorf("Invalid code: %v", w.Code) + } + if w.Header().Get("Content-Type") != "applicaiton/json; charset=utf-8" { + t.Errorf("Insufficient headers: %v", w.Header()) + } + body := w.Body + dec := json.NewDecoder(body) + var d data + if err := dec.Decode(&d); err != nil || d.Fortune != "大凶" { + t.Errorf("Failed to decode: %v", err) + } +} diff --git a/kadai4/en-ken/reame.md b/kadai4/en-ken/reame.md new file mode 100644 index 0000000..6cd0128 --- /dev/null +++ b/kadai4/en-ken/reame.md @@ -0,0 +1,14 @@ +# 課題4 + +おみくじ API を作りましょう + +- JSON形式でおみくじの結果を返す +- 正月 (1/1-1/3) だけ大吉にする +- ハンドラのテストを書いてみる + +## 使い方 + +```go +go get github.com/gopherdojo/dojo6/kadai4/en-ken/kadai4 +kadai4 +```