Beispiel #1
0
func TestFormationList(t *testing.T) {
	models.Test(t, func() {
		formation := structs.Formation{
			structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}},
			structs.ProcessFormation{Name: "worker", Count: 3, CPU: 129, Memory: 1025, Ports: []int{4000, 4001}},
		}

		models.TestProvider.On("FormationList", "myapp").Return(formation, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/myapp/formation", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `[
				{"balancer":"", "count":2, "cpu":128, "memory":1024, "name":"web", "ports":[3000,3001]},
				{"balancer":"", "count":3, "cpu":129, "memory":1025, "name":"worker", "ports":[4000,4001]}
			]`)
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("FormationList", "myapp").Return(nil, fmt.Errorf("some error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/myapp/formation", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "some error")
		}
	})
}
Beispiel #2
0
func TestProcessStop(t *testing.T) {
	models.Test(t, func() {
		models.TestProvider.On("ProcessStop", "myapp-staging", "p1234").Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/apps/myapp-staging/processes/p1234", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `{"success":true}`)
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessStop", "myapp-staging", "p1234").Return(test.ErrorNotFound("no such process"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/apps/myapp-staging/processes/p1234", nil)) {
			hf.AssertCode(t, 404)
			hf.AssertError(t, "no such process")
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessStop", "myapp-staging", "p1234").Return(fmt.Errorf("unknown error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/apps/myapp-staging/processes/p1234", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "unknown error")
		}
	})
}
Beispiel #3
0
func TestProcessList(t *testing.T) {
	models.Test(t, func() {
		processes := structs.Processes{
			structs.Process{
				ID:       "foo",
				App:      "myapp-staging",
				Name:     "procname",
				Release:  "R123",
				Command:  "ls -la",
				Host:     "127.0.0.1",
				Image:    "image:tag",
				Instance: "i-1234",
				Ports:    []string{"80", "443"},
				CPU:      0.345,
				Memory:   0.456,
				Started:  time.Unix(1473483567, 0).UTC(),
			},
		}

		models.TestProvider.On("ProcessList", "myapp-staging").Return(processes, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/myapp-staging/processes", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, "[{\"app\":\"myapp-staging\",\"command\":\"ls -la\",\"cpu\":0.345,\"host\":\"127.0.0.1\",\"id\":\"foo\",\"image\":\"image:tag\",\"instance\":\"i-1234\",\"memory\":0.456,\"name\":\"procname\",\"ports\":[\"80\",\"443\"],\"release\":\"R123\",\"started\":\"2016-09-10T04:59:27Z\"}]")
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessList", "myapp-staging").Return(nil, test.ErrorNotFound("no such process"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/myapp-staging/processes", nil)) {
			hf.AssertCode(t, 404)
			hf.AssertError(t, "no such process")
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessList", "myapp-staging").Return(nil, fmt.Errorf("unknown error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/myapp-staging/processes", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "unknown error")
		}
	})
}
Beispiel #4
0
func TestFormationSetNonNumeric(t *testing.T) {
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "foo")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "count must be numeric")
		}
	})

	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("cpu", "foo")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "cpu must be numeric")
		}
	})

	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("memory", "foo")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "memory must be numeric")
		}
	})
}
Beispiel #5
0
func TestSystemUpdateSaveError(t *testing.T) {
	models.Test(t, func() {
		before := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}
		change := structs.System{
			Count:   4,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}

		models.TestProvider.On("SystemGet").Return(before, nil)
		models.TestProvider.On("SystemSave", change).Return(fmt.Errorf("bad save"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "4")

		if assert.Nil(t, hf.Request("PUT", "/system", v)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "bad save")
		}
	})
}
Beispiel #6
0
func TestSystemUpdateAutoscaleCount(t *testing.T) {
	models.Test(t, func() {
		as := os.Getenv("AUTOSCALE")
		os.Setenv("AUTOSCALE", "true")
		defer os.Setenv("AUTOSCALE", as)

		before := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}

		models.TestProvider.On("SystemGet").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "5")

		if assert.Nil(t, hf.Request("PUT", "/system", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "scaling count prohibited when autoscale enabled")
		}
	})
}
Beispiel #7
0
func TestSystemUpdate(t *testing.T) {
	models.Test(t, func() {
		before := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}
		change := structs.System{
			Count:   5,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.test",
			Version: "latest",
		}

		models.TestProvider.On("SystemGet").Return(before, nil)
		models.TestProvider.On("SystemSave", change).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "5")
		v.Add("type", "t2.test")
		v.Add("version", "latest")

		if assert.Nil(t, hf.Request("PUT", "/system", v)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `{"count":5,"name":"test","region":"us-test-1","status":"running","type":"t2.test","version":"latest"}`)
		}
	})
}
Beispiel #8
0
func TestInstanceList(t *testing.T) {
	models.Test(t, func() {
		instances := structs.Instances{
			structs.Instance{
				Agent:     true,
				Cpu:       0.28,
				Id:        "test",
				Memory:    0.18,
				PrivateIp: "1.2.3.4",
				Processes: 5,
				PublicIp:  "2.3.4.5",
				Status:    "running",
				Started:   time.Unix(1475610360, 0).UTC(),
			},
		}

		models.TestProvider.On("InstanceList").Return(instances, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/instances", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, "[{\"agent\":true,\"cpu\":0.28,\"id\":\"test\",\"memory\":0.18,\"private-ip\":\"1.2.3.4\",\"processes\":5,\"public-ip\":\"2.3.4.5\",\"started\":\"2016-10-04T19:46:00Z\",\"status\":\"running\"}]")
		}
	})
}
Beispiel #9
0
func TestReleaseList(t *testing.T) {
	models.Test(t, func() {
		releases := structs.Releases{
			structs.Release{
				Id:       "RVFETUHHKKD",
				App:      "httpd",
				Build:    "BHINCLZYYVN",
				Env:      "foo=bar",
				Manifest: "web:\n  image: httpd\n  ports:\n  - 80:80\n",
				Created:  time.Unix(1459780542, 627770380).UTC(),
			},
			structs.Release{
				Id:       "RFVZFLKVTYO",
				App:      "httpd",
				Build:    "BNOARQMVHUO",
				Env:      "foo=bar",
				Manifest: "web:\n  image: httpd\n  ports:\n  - 80:80\n",
				Created:  time.Unix(1459709199, 166694813).UTC(),
			},
		}

		models.TestProvider.On("ReleaseList", "example", int64(20)).Return(releases, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/apps/example/releases", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, "[{\"app\":\"httpd\",\"build\":\"BHINCLZYYVN\",\"created\":\"2016-04-04T14:35:42.62777038Z\",\"env\":\"foo=bar\",\"id\":\"RVFETUHHKKD\",\"manifest\":\"web:\\n  image: httpd\\n  ports:\\n  - 80:80\\n\"},{\"app\":\"httpd\",\"build\":\"BNOARQMVHUO\",\"created\":\"2016-04-03T18:46:39.166694813Z\",\"env\":\"foo=bar\",\"id\":\"RFVZFLKVTYO\",\"manifest\":\"web:\\n  image: httpd\\n  ports:\\n  - 80:80\\n\"}]")
		}
	})
}
Beispiel #10
0
func TestBuildDelete(t *testing.T) {
	models.Test(t, func() {
		build := &structs.Build{
			App:         "myapp",
			Description: "desc",
			Ended:       time.Unix(1475611334, 0).UTC(),
			Id:          "B1234",
			Logs:        "",
			Manifest:    "",
			Reason:      "",
			Release:     "R2345",
			Started:     time.Unix(1475611334, 0).UTC(),
			Status:      "complete",
		}

		models.TestProvider.On("ReleaseDelete", "example", "B1234").Return(nil)
		models.TestProvider.On("BuildDelete", "example", "B1234").Return(build, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/apps/example/builds/B1234", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, "{\"app\":\"myapp\",\"description\":\"desc\",\"ended\":\"2016-10-04T20:02:14Z\",\"id\":\"B1234\",\"logs\":\"\",\"manifest\":\"\",\"reason\":\"\",\"release\":\"R2345\",\"started\":\"2016-10-04T20:02:14Z\",\"status\":\"complete\"}")
		}
	})
}
Beispiel #11
0
func TestSystemUpdateBadCount(t *testing.T) {
	models.Test(t, func() {
		before := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}

		models.TestProvider.On("SystemGet").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "foo")

		if assert.Nil(t, hf.Request("PUT", "/system", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "count must be numeric")
		}
	})

	models.Test(t, func() {
		before := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}

		models.TestProvider.On("SystemGet").Return(before, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "-2")

		if assert.Nil(t, hf.Request("PUT", "/system", v)) {
			hf.AssertCode(t, 403)
			hf.AssertError(t, "count must be greater than 1")
		}
	})
}
Beispiel #12
0
func TestProcessRunDetached(t *testing.T) {
	opts := structs.ProcessRunOptions{
		Command: "test-command",
		Release: "R1234",
	}

	v := url.Values{}
	v.Add("command", "test-command")
	v.Add("release", "R1234")

	models.Test(t, func() {
		models.TestProvider.On("ProcessRun", "myapp-staging", "web", opts).Return("pid", nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("POST", "/apps/myapp-staging/processes/web/run", v)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `{"success":true}`)
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessRun", "myapp-staging", "web", opts).Return("", test.ErrorNotFound("no such process"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("POST", "/apps/myapp-staging/processes/web/run", v)) {
			hf.AssertCode(t, 404)
			hf.AssertError(t, "no such process")
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("ProcessRun", "myapp-staging", "web", opts).Return("", fmt.Errorf("unknown error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("POST", "/apps/myapp-staging/processes/web/run", v)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "unknown error")
		}
	})
}
Beispiel #13
0
func TestSystemUpdateRackFetchError(t *testing.T) {
	models.Test(t, func() {
		models.TestProvider.On("SystemGet").Return(nil, fmt.Errorf("some error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("PUT", "/system", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "some error")
		}
	})
}
Beispiel #14
0
func TestSystemReleasesError(t *testing.T) {
	models.Test(t, func() {
		models.TestProvider.On("SystemReleases").Return(nil, fmt.Errorf("some error"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/system/releases", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "some error")
		}
	})
}
Beispiel #15
0
func TestInstanceTerminate(t *testing.T) {
	models.Test(t, func() {
		models.TestProvider.On("InstanceTerminate", "i-1234").Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/instances/i-1234", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})

	models.Test(t, func() {
		models.TestProvider.On("InstanceTerminate", "i-1234").Return(fmt.Errorf("broken"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("DELETE", "/instances/i-1234", nil)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "broken")
		}
	})
}
Beispiel #16
0
func TestFormationSetFailedGet(t *testing.T) {
	models.Test(t, func() {
		models.TestProvider.On("FormationGet", "myapp", "web").Return(nil, fmt.Errorf("could not fetch"))

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "4")
		v.Add("cpu", "200")
		v.Add("memory", "300")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 500)
			hf.AssertError(t, "could not fetch")
		}
	})
}
Beispiel #17
0
func TestFormationSetOne(t *testing.T) {
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 200, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("cpu", "200")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})
}
Beispiel #18
0
func TestSystemReleases(t *testing.T) {
	models.Test(t, func() {
		releases := structs.Releases{
			structs.Release{Id: "R0000001", App: "test", Build: "B0000001", Created: time.Date(2016, 3, 4, 5, 6, 7, 12, time.UTC)},
			structs.Release{Id: "R0000002", App: "test", Build: "B0000002", Created: time.Date(2016, 3, 4, 9, 6, 7, 14, time.UTC)},
		}

		models.TestProvider.On("SystemReleases").Return(releases, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/system/releases", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `[
				{"app":"test","build":"B0000001","created":"2016-03-04T05:06:07.000000012Z","env":"","id":"R0000001","manifest":""},
				{"app":"test","build":"B0000002","created":"2016-03-04T09:06:07.000000014Z","env":"","id":"R0000002","manifest":""}
			]`)
		}
	})
}
Beispiel #19
0
func TestSystemShow(t *testing.T) {
	models.Test(t, func() {
		system := &structs.System{
			Count:   3,
			Name:    "test",
			Region:  "us-test-1",
			Status:  "running",
			Type:    "t2.small",
			Version: "dev",
		}

		models.TestProvider.On("SystemGet").Return(system, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/system", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `{"count":3,"name":"test","region":"us-test-1","status":"running","type":"t2.small","version":"dev"}`)
		}
	})
}
Beispiel #20
0
func TestSystemCapacity(t *testing.T) {
	models.Test(t, func() {
		capacity := &structs.Capacity{
			ClusterCPU:     200,
			ClusterMemory:  2048,
			InstanceCPU:    100,
			InstanceMemory: 2048,
			ProcessCount:   10,
			ProcessMemory:  1928,
			ProcessCPU:     84,
			ProcessWidth:   3,
		}

		models.TestProvider.On("CapacityGet").Return(capacity, nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		if assert.Nil(t, hf.Request("GET", "/system/capacity", nil)) {
			hf.AssertCode(t, 200)
			hf.AssertJSON(t, `{"cluster-cpu":200,"cluster-memory":2048,"instance-cpu":100,"instance-memory":2048,"process-count":10,"process-memory":1928,"process-cpu":84,"process-width":3}`)
		}
	})
}
Beispiel #21
0
func TestFormationSetEdgeCases(t *testing.T) {

	// count=-1 with older rack versions means no change
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 200, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)
		hf.SetVersion("20160602213112")

		v := url.Values{}
		v.Add("count", "-1")
		v.Add("cpu", "200")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})

	// count=-2 means no change
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 200, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "-2")
		v.Add("cpu", "200")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})

	// cpu=-1 means no change
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 4, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "4")
		v.Add("cpu", "-1")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})

	// memory=0 means no change
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 4, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "4")
		v.Add("memory", "0")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})

	// memory=-1 means no change
	models.Test(t, func() {
		before := &structs.ProcessFormation{Name: "web", Count: 2, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}
		after := &structs.ProcessFormation{Name: "web", Count: 4, CPU: 128, Memory: 1024, Ports: []int{3000, 3001}}

		models.TestProvider.On("FormationGet", "myapp", "web").Return(before, nil)
		models.TestProvider.On("FormationSave", "myapp", after).Return(nil)

		hf := test.NewHandlerFunc(controllers.HandlerFunc)

		v := url.Values{}
		v.Add("count", "4")
		v.Add("memory", "-1")

		if assert.Nil(t, hf.Request("POST", "/apps/myapp/formation/web", v)) {
			hf.AssertCode(t, 200)
			hf.AssertSuccess(t)
		}
	})
}