Starting to do my own thing
continuous-integration/drone/push Build is passing Details

main
Drew Bednar 2 months ago
parent dff48a667e
commit a809c048c4

@ -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() {

@ -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)
}

@ -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

@ -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)
}
})
}

Loading…
Cancel
Save