From 3020c2a88741a97cc0b7b62cd99490f9bab03fab Mon Sep 17 00:00:00 2001 From: David Keijser Date: Sat, 30 Apr 2016 12:31:14 +0200 Subject: [PATCH 1/3] Add a few tests of task struct --- types/task_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/types/task_test.go b/types/task_test.go index bbd675e..98dbb61 100644 --- a/types/task_test.go +++ b/types/task_test.go @@ -108,6 +108,12 @@ func TestTask(t *testing.T) { So(task.IsRunning(), ShouldBeTrue) }) + + Convey("A empty task", func() { + task := EremeticTask{} + + So(task.IsRunning(), ShouldBeFalse) + }) }) Convey("LastUpdated", t, func() { @@ -132,4 +138,17 @@ func TestTask(t *testing.T) { So(s.Unix(), ShouldEqual, 0) }) }) + + Convey("NewEremeticTask", t, func() { + Convey("New task from empty request", func() { + req := Request{} + task, err := NewEremeticTask(req) + + So(err, ShouldBeNil) + So(task, ShouldNotBeNil) + So(task.WasRunning(), ShouldBeFalse) + So(task.IsRunning(), ShouldBeFalse) + So(task.IsTerminated(), ShouldBeFalse) + }) + }) } From 4404a1ebab1a3cff16a045e245235cb5ad62e0d2 Mon Sep 17 00:00:00 2001 From: David Keijser Date: Tue, 10 May 2016 19:37:42 +0200 Subject: [PATCH 2/3] Negative tests of http handlers --- handler/handler_test.go | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/handler/handler_test.go b/handler/handler_test.go index 7874474..fb31935 100644 --- a/handler/handler_test.go +++ b/handler/handler_test.go @@ -3,6 +3,7 @@ package handler import ( "bytes" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -29,12 +30,24 @@ func (m mockError) Error() string { } type mockScheduler struct { + nextError *error } func (s *mockScheduler) ScheduleTask(request types.Request) (string, error) { + if err := s.nextError; err != nil { + s.nextError = nil + return "", *err + } return "eremetic-task.mock", nil } +type errorReader struct { +} + +func (r *errorReader) Read(p []byte) (int, error) { + return 0, errors.New("oh no") +} + func TestHandling(t *testing.T) { scheduler := &mockScheduler{} status := []types.Status{ @@ -157,5 +170,39 @@ func TestHandling(t *testing.T) { So(location, ShouldStartWith, "http://localhost/task/eremetic-task.") So(wr.Code, ShouldEqual, http.StatusAccepted) }) + + Convey("Failed to schedule", func() { + data := []byte(`{"task_mem":22.0, "docker_image": "busybox", "command": "echo hello", "task_cpus":0.5, "tasks_to_launch": 1}`) + r, _ := http.NewRequest("POST", "/task", bytes.NewBuffer(data)) + r.Host = "localhost" + err := errors.New("A random error") + scheduler.nextError = &err + + handler := AddTask(scheduler) + handler(wr, r) + + So(wr.Code, ShouldEqual, 500) + }) + + Convey("Error on bad input stream", func() { + r, _ := http.NewRequest("POST", "/task", &errorReader{}) + r.Host = "localhost" + + handler := AddTask(scheduler) + handler(wr, r) + + So(wr.Code, ShouldEqual, 422) + }) + + Convey("Error on malformed json", func() { + data := []byte(`{"key:123}`) + r, _ := http.NewRequest("POST", "/task", bytes.NewBuffer(data)) + r.Host = "localhost" + + handler := AddTask(scheduler) + handler(wr, r) + + So(wr.Code, ShouldEqual, 422) + }) }) } From 81cc8a5d7b956f6b3449adb8f03a09f935b5be79 Mon Sep 17 00:00:00 2001 From: David Keijser Date: Tue, 10 May 2016 20:09:22 +0200 Subject: [PATCH 3/3] Test basic scheduling scenarios --- scheduler/match_test.go | 9 ++++++- scheduler/scheduler_test.go | 50 ++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/scheduler/match_test.go b/scheduler/match_test.go index da1debe..6521002 100644 --- a/scheduler/match_test.go +++ b/scheduler/match_test.go @@ -3,8 +3,8 @@ package scheduler import ( "testing" - "github.com/klarna/eremetic/types" "github.com/golang/protobuf/proto" + "github.com/klarna/eremetic/types" mesos "github.com/mesos/mesos-go/mesosproto" "github.com/mesos/mesos-go/mesosutil" . "github.com/smartystreets/goconvey/convey" @@ -15,6 +15,13 @@ func offer(id string, cpu float64, mem float64) *mesos.Offer { Id: &mesos.OfferID{ Value: proto.String(id), }, + FrameworkId: &mesos.FrameworkID{ + Value: proto.String("framework-1234"), + }, + SlaveId: &mesos.SlaveID{ + Value: proto.String("slave-1234"), + }, + Hostname: proto.String("localhost"), Resources: []*mesos.Resource{ mesosutil.NewScalarResource("cpus", cpu), mesosutil.NewScalarResource("mem", mem), diff --git a/scheduler/scheduler_test.go b/scheduler/scheduler_test.go index c713cf5..505ae27 100644 --- a/scheduler/scheduler_test.go +++ b/scheduler/scheduler_test.go @@ -46,7 +46,9 @@ func TestScheduler(t *testing.T) { defer database.Close() Convey("eremeticScheduler", t, func() { - s := eremeticScheduler{} + s := &eremeticScheduler{ + tasks: make(chan string, 1), + } id := "eremetic-task.9999" database.PutTask(&types.EremeticTask{ID: id}) @@ -106,18 +108,60 @@ func TestScheduler(t *testing.T) { Convey("ResourceOffers", func() { driver := NewMockScheduler() - var offers []*mesos.Offer Convey("No offers", func() { + offers := []*mesos.Offer{} s.ResourceOffers(driver, offers) So(driver.AssertNotCalled(t, "DeclineOffer"), ShouldBeTrue) So(driver.AssertNotCalled(t, "LaunchTasks"), ShouldBeTrue) }) Convey("No tasks", func() { - offers = append(offers, &mesos.Offer{Id: &mesos.OfferID{Value: proto.String("1234")}}) + offers := []*mesos.Offer{ + offer("1234", 1.0, 128), + } + driver.On("DeclineOffer").Return("declined").Once() + s.ResourceOffers(driver, offers) + So(driver.AssertCalled(t, "DeclineOffer"), ShouldBeTrue) + So(driver.AssertNotCalled(t, "LaunchTasks"), ShouldBeTrue) + }) + + Convey("One task able to launch", func() { + offers := []*mesos.Offer{ + offer("1234", 1.0, 128), + } + driver.On("LaunchTasks").Return("launched").Once() + + _, err := s.ScheduleTask(types.Request{ + TaskCPUs: 0.5, + TaskMem: 22.0, + DockerImage: "busybox", + Command: "echo hello", + }) + + So(err, ShouldBeNil) + s.ResourceOffers(driver, offers) + + So(driver.AssertNotCalled(t, "DeclineOffer"), ShouldBeTrue) + So(driver.AssertCalled(t, "LaunchTasks"), ShouldBeTrue) + }) + + Convey("One task unable to launch", func() { + offers := []*mesos.Offer{ + offer("1234", 1.0, 128), + } driver.On("DeclineOffer").Return("declined").Once() + + _, err := s.ScheduleTask(types.Request{ + TaskCPUs: 1.5, + TaskMem: 22.0, + DockerImage: "busybox", + Command: "echo hello", + }) + + So(err, ShouldBeNil) s.ResourceOffers(driver, offers) + So(driver.AssertCalled(t, "DeclineOffer"), ShouldBeTrue) So(driver.AssertNotCalled(t, "LaunchTasks"), ShouldBeTrue) })