diff --git a/cmd/bugbox/main.go b/cmd/bugbox/main.go index 760856f..820ff69 100644 --- a/cmd/bugbox/main.go +++ b/cmd/bugbox/main.go @@ -9,8 +9,12 @@ import ( type InMemoryEnclosureStore struct{} -func (i *InMemoryEnclosureStore) GetEnclosure(name string) string { - return name +func (i *InMemoryEnclosureStore) GetEnclosure(id uint64) (*bugbox.Enclosure, bool) { + return &bugbox.Enclosure{Id: id}, true +} + +func (i *InMemoryEnclosureStore) RecordEvent(id uint64, event string) error { + return nil } func main() { diff --git a/enclosure.go b/enclosure.go index 5aa1923..cad4c60 100644 --- a/enclosure.go +++ b/enclosure.go @@ -1 +1,19 @@ package bugbox + +import "fmt" + +type Enclosure struct { + Id uint64 + Temp float64 + Humidity float64 + Light bool + Events []string +} + +func (e *Enclosure) String() string { + return fmt.Sprintf("%d", e.Id) +} + +func (e *Enclosure) RecordEvent(event string) { + e.Events = append(e.Events, event) +} diff --git a/server.go b/server.go index e9a640a..3ed09d3 100644 --- a/server.go +++ b/server.go @@ -3,13 +3,15 @@ package bugbox import ( "fmt" "net/http" + "strconv" "strings" ) // EnclosureStore describes an interface to managing Enclosures type EnclosureStore interface { // Retrieves an enclosure by name - GetEnclosure(name string) string + GetEnclosure(id uint64) (enclosure *Enclosure, ok bool) + RecordEvent(id uint64, event string) error } type BugBoxServer struct { @@ -18,13 +20,62 @@ type BugBoxServer struct { // This implements the Handler interface func (b *BugBoxServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - enclosure := strings.TrimPrefix(r.URL.Path, "/enclosure/") - e := b.EnclosureStore.GetEnclosure(enclosure) - if e == "" { + + switch r.Method { + case http.MethodPost: + b.processPostRequest(w, r) + case http.MethodGet: + b.retrieveEnclosure(w, r) + } + +} + +func (b *BugBoxServer) processPostRequest(w http.ResponseWriter, r *http.Request) { + strId := strings.TrimPrefix(r.URL.Path, "/enclosure/") + + // TODO this is getting big but once again we are just trying to get it to pass + if strings.Contains(strId, "events") { + event := []byte{} + strId = strings.Split(strId, "/")[0] + id, _ := strconv.ParseUint(strId, 10, 64) + + // Handle the case where the body is emtpy + if r.Body == nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + r.Body.Read(event) + err := b.EnclosureStore.RecordEvent(id, string(event)) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + w.WriteHeader(http.StatusAccepted) + } else { + b.createEnclosure(w) + } +} + +func (b *BugBoxServer) createEnclosure(w http.ResponseWriter) { + w.WriteHeader(http.StatusAccepted) +} + +func (b *BugBoxServer) retrieveEnclosure(w http.ResponseWriter, r *http.Request) { + strId := strings.TrimPrefix(r.URL.Path, "/enclosure/") + id, err := strconv.ParseUint(strId, 10, 64) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + e, ok := b.EnclosureStore.GetEnclosure(id) + if !ok { w.WriteHeader(http.StatusNotFound) + return } - fmt.Fprint(w, e) + fmt.Fprint(w, e.String()) } // GetEnclosure retrieves the requested enclosure diff --git a/server_test.go b/server_test.go index 90efba1..765c81d 100644 --- a/server_test.go +++ b/server_test.go @@ -1,14 +1,21 @@ package bugbox import ( + "bytes" "fmt" "net/http" "net/http/httptest" "testing" ) -func newGETEnclosureRequest(name string) *http.Request { - request, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("/enclosure/%s", name), nil) +func newGETEnclosureRequest(id uint64) *http.Request { + request, _ := http.NewRequest(http.MethodGet, fmt.Sprintf("/enclosure/%d", id), nil) + return request +} + +func newPOSTEventRequest(id uint64, value string) *http.Request { + body := []byte(value) + request, _ := http.NewRequest(http.MethodPost, fmt.Sprintf("/enclosure/%d/events", id), bytes.NewBuffer(body)) return request } @@ -28,25 +35,35 @@ func assertStatus(t testing.TB, got, want int) { } type MockEnclosureStore struct { - enclosures map[string]string + enclosures map[uint64]*Enclosure +} + +func (s *MockEnclosureStore) GetEnclosure(id uint64) (enclosure *Enclosure, ok bool) { + enclosure, ok = s.enclosures[id] + return } -func (s *MockEnclosureStore) GetEnclosure(name string) string { - e := s.enclosures[name] - return e +func (s *MockEnclosureStore) RecordEvent(id uint64, event string) error { + enc, ok := s.enclosures[id] + if !ok { + return fmt.Errorf("Failed to find enclosure %d", id) + } + enc.RecordEvent(event) + return nil } func TestGETEnclosures(t *testing.T) { mockEnclosureStore := MockEnclosureStore{ - map[string]string{ - "1337": "1337", - "7331": "7331"}, + map[uint64]*Enclosure{ + 1337: &Enclosure{Id: 1337}, + 7331: &Enclosure{Id: 7331}, + }, } server := &BugBoxServer{EnclosureStore: &mockEnclosureStore} t.Run("returns enclosure 1337", func(t *testing.T) { // nil is used since we are not providing a request body - request := newGETEnclosureRequest("1337") + request := newGETEnclosureRequest(1337) // response is a ResponseRecorder used for spying on response response := httptest.NewRecorder() @@ -58,7 +75,7 @@ func TestGETEnclosures(t *testing.T) { }) t.Run("returns enclosure 7331", func(t *testing.T) { // nil is used since we are not providing a request body - request := newGETEnclosureRequest("7331") + request := newGETEnclosureRequest(7331) // response is a ResponseRecorder used for spying on response response := httptest.NewRecorder() @@ -69,7 +86,7 @@ func TestGETEnclosures(t *testing.T) { }) t.Run("returns 404 when enclosure missing", func(t *testing.T) { - request := newGETEnclosureRequest("9000") + request := newGETEnclosureRequest(9000) response := httptest.NewRecorder() server.ServeHTTP(response, request) @@ -77,3 +94,24 @@ func TestGETEnclosures(t *testing.T) { assertStatus(t, response.Code, http.StatusNotFound) }) } + +func TestStoreEnclosure(t *testing.T) { + testEnclosure := &Enclosure{Id: 2057} + store := MockEnclosureStore{ + map[uint64]*Enclosure{2057: testEnclosure}, + } + + server := &BugBoxServer{EnclosureStore: &store} + + t.Run("it accepts a POST request for an event", func(t *testing.T) { + request := newPOSTEventRequest(2057, "dirp") + response := httptest.NewRecorder() + + server.ServeHTTP(response, request) + assertStatus(t, response.Code, http.StatusAccepted) + + if len(testEnclosure.Events) != 1 { + t.Errorf("Got %d calls to RecordEvent, want %d", len(testEnclosure.Events), 1) + } + }) +}