From 6ff83ff680f64bed933abe0127deb6d24bf7d276 Mon Sep 17 00:00:00 2001 From: Nicolas Dextraze Date: Tue, 16 Feb 2016 21:30:50 -0800 Subject: [PATCH] simpleserver replies with error instead of crashing, adding tests on storage --- goes_test.go | 147 ++++++++++++++++++++++++----------- simpleserver/simpleserver.go | 12 ++- 2 files changed, 109 insertions(+), 50 deletions(-) diff --git a/goes_test.go b/goes_test.go index e02ce77..eeb1ba7 100644 --- a/goes_test.go +++ b/goes_test.go @@ -4,17 +4,16 @@ import ( "testing" "github.com/satori/go.uuid" - "crypto/rand" "os" "path" "reflect" - "fmt" - "math/big" + "io/ioutil" + "bytes" ) var tempDir string -type MyEvent struct { +type AnEvent struct { A int64 B string } @@ -29,7 +28,7 @@ func setUp() { tempDir := path.Join(os.TempDir(), uuid.NewV4().String()) storage := NewDiskStorage(tempDir) SetStorage(storage) - serializer := NewJsonSerializer((*MyEvent)(nil), (*AnotherEvent)(nil)) + serializer := NewJsonSerializer((*AnEvent)(nil), (*AnotherEvent)(nil)) SetSerializer(serializer) } @@ -40,44 +39,78 @@ func tearDown() { } } -func createRandomEvent() *Event { - id := uuid.NewV4() - return createRandomEventFor(id) +func wrapEvent(aggregateId uuid.UUID, event interface{}) Event { + return Event{aggregateId, event} } -func createRandomEventFor(id uuid.UUID) *Event { - a, _ := rand.Int(rand.Reader, big.NewInt(100000)) - b, _ := rand.Int(rand.Reader, big.NewInt(1000000)) - payload := MyEvent{a.Int64(), fmt.Sprintf("abc-%v", b.Int64())} - return &Event{id, payload} -} - -func TestAddEvent(t *testing.T) { +func TestSerializeEventToJson(t *testing.T) { setUp() defer tearDown() - ev := createRandomEvent() - err := AddEvent(*ev) + ev := wrapEvent(uuid.NewV4(), AnEvent{int64(1024), "Tests"}) + err := AddEvent(ev) if err != nil { t.Errorf("AddEvent failed with %q", err) + return + } + + filename := (storage.(*DiskStorage)).getFilenameForEvents(ev.AggregateId.String()); + if fi, _ := os.Stat(filename); fi == nil { + t.Errorf("AddEvent failed to create file %q", filename) + return + } + content, _ := ioutil.ReadFile(filename) + if !bytes.Contains(content, []byte("{\"A\":1024,\"B\":\"Tests\"}")) { + t.Errorf("AddEvent failed. File doesn't contain event json.") + return } } -func TestAddEventsToSameAggregate(t *testing.T) { +func TestSerializeEventsForSameAggregateInSameFile(t *testing.T) { setUp() defer tearDown() - id := uuid.NewV4() - ev1 := createRandomEventFor(id) - err := AddEvent(*ev1) + aggregateId := uuid.NewV4() + ev1 := wrapEvent(aggregateId, AnEvent{int64(12345), "Hello"}) + err := AddEvent(ev1) if err != nil { - t.Errorf("AddEvent() failed with %q", err) + t.Errorf("AddEvent failed with %q", err) return } - ev2 := createRandomEventFor(id) - err = AddEvent(*ev2) + ev2 := wrapEvent(aggregateId, AnotherEvent{int64(23456), "Bob", 123.45}) + err = AddEvent(ev2) if err != nil { - t.Errorf("AddEvent() failed with %q", err) + t.Errorf("AddEvent failed with %q", err) + return + } + + filename := (storage.(*DiskStorage)).getFilenameForEvents(aggregateId.String()) + content, _ := ioutil.ReadFile(filename) + if !bytes.Contains(content, []byte("Hello")) || !bytes.Contains(content, []byte("Bob")) { + t.Error("AddEvent failed. Both events are not serialized in same file.") + return + } +} + +func TestTypeInformationIsProvided(t *testing.T) { + setUp() + defer tearDown() + + ev := wrapEvent(uuid.NewV4(), AnEvent{int64(1024), "Tests"}) + err := AddEvent(ev) + if err != nil { + t.Errorf("AddEvent failed with %q", err) + return + } + + filename := (storage.(*DiskStorage)).getFilenameForEvents(ev.AggregateId.String()); + if fi, _ := os.Stat(filename); fi == nil { + t.Errorf("AddEvent failed to create file %q", filename) + return + } + content, _ := ioutil.ReadFile(filename) + if !bytes.Contains(content, []byte("AnEvent")) { + t.Errorf("AddEvent failed. File doesn't contain event type.") return } } @@ -86,43 +119,63 @@ func (me *Event) Equals(other *Event) bool { return me.AggregateId == other.AggregateId && reflect.DeepEqual(me.Payload, other.Payload) } -func TestRetrieveFor(t *testing.T) { +func TestEventsCanBeRetrieved(t *testing.T) { setUp() defer tearDown() - id := uuid.NewV4() - ev1 := createRandomEventFor(id) - ev2 := createRandomEventFor(id) - AddEvent(*ev1) - AddEvent(*ev2) - AddEvent(*createRandomEvent()) + aggregateId := uuid.NewV4() + ev1 := wrapEvent(aggregateId, AnEvent{int64(12345), "Hello"}) + err := AddEvent(ev1) + if err != nil { + t.Errorf("AddEvent failed with %q", err) + return + } + ev2 := wrapEvent(aggregateId, AnotherEvent{int64(23456), "Bob", 123.45}) + err = AddEvent(ev2) + if err != nil { + t.Errorf("AddEvent failed with %q", err) + return + } - events, err := RetrieveFor(id) + events, err := RetrieveFor(aggregateId) switch { case err != nil: - t.Errorf("RetrieveFor(%q) failed with %q", id.String(), err) + t.Errorf("RetrieveFor(%q) failed with %q", aggregateId.String(), err) case len(events) != 2: - t.Errorf("RetrieveFor(%q) returned %v events, expected %v", id.String(), len(events), 2) - case !events[0].Equals(ev1): - t.Errorf("RetrieveFor(%q) first event doesn't match %+v != %+v", id.String(), events[0], ev1) - case !events[1].Equals(ev2): - t.Errorf("RetrieveFor(%q) second event doesn't match %+v != %+v", id.String(), events[1], ev2) + t.Errorf("RetrieveFor(%q) returned %v events, expected %v", aggregateId.String(), len(events), 2) + case !ev1.Equals(events[0]): + t.Errorf("RetrieveFor(%q) first event doesn't match %+v != %+v", aggregateId.String(), events[0], ev1) + case !ev2.Equals(events[1]): + t.Errorf("RetrieveFor(%q) second event doesn't match %+v != %+v", aggregateId.String(), events[1], ev2) } } -func TestRetrieveAll(t *testing.T) { +func TestEventsCanBeReplayedInOrder(t *testing.T) { setUp() defer tearDown() - AddEvent(*createRandomEvent()) - AddEvent(*createRandomEvent()) - AddEvent(*createRandomEvent()) + aggregateId1 := uuid.NewV4() + aggregateId2 := uuid.NewV4() + testEvent1 := wrapEvent(aggregateId1, AnEvent{int64(123), "Hello 1"}) + testEvent2 := wrapEvent(aggregateId2, AnEvent{int64(456), "Hello 2"}) + testEvent3 := wrapEvent(aggregateId1, AnEvent{int64(789), "Hello 3"}) + AddEvent(testEvent1) + AddEvent(testEvent2) + AddEvent(testEvent3) events, err := RetrieveAll() switch { case err != nil: - t.Errorf("RetrieveAll() failed with %q", err) + t.Errorf("RetrieveAll failed with %q", err) case len(events) != 3: - t.Errorf("RetrieveAll() returned %v events, expected %v", len(events), 3) + t.Errorf("RetrieveAll returned %v events, expected %v", len(events), 3) + case !testEvent1.Equals(events[0]) || !testEvent2.Equals(events[1]) || !testEvent3.Equals(events[2]): + t.Error("RetrieveAll returned events in wrong order.") } -} \ No newline at end of file +} + +/* + Missing tests from https://gist.github.com/adymitruk/b4627b74617a37b6d949 + - GUID reversal for distribution + - Created date stored with event + */ \ No newline at end of file diff --git a/simpleserver/simpleserver.go b/simpleserver/simpleserver.go index 8e087be..1282be2 100644 --- a/simpleserver/simpleserver.go +++ b/simpleserver/simpleserver.go @@ -57,7 +57,9 @@ func main() { data := message[2] err = goes.AddEvent(goes.Event{aggregateId, data}) if err != nil { - panic(err) + replySocket.Send(fmt.Sprintf("Error: %v", err), 0) + fmt.Println(err) + break } replySocket.Send("Ok", 0) case "ReadStream": @@ -69,14 +71,18 @@ func main() { fmt.Println("->", command, aggregateId.String()) events, err := goes.RetrieveFor(aggregateId) if err != nil { - panic(err) + replySocket.Send(fmt.Sprintf("Error: %v", err), 0) + fmt.Println(err) + break } sendEvents(replySocket, events) case "ReadAll": fmt.Println("->", command) events, err := goes.RetrieveAll() if err != nil { - panic(err) + replySocket.Send(fmt.Sprintf("Error: %v", err), 0) + fmt.Println(err) + break } sendEvents(replySocket, events) }