"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
)

var _ = Describe("Copy app bits", func() {
	var golangAppName string
	var helloWorldAppName string

	BeforeEach(func() {
		golangAppName = generator.PrefixedRandomName("CATS-APP-")
		helloWorldAppName = generator.PrefixedRandomName("CATS-APP-")

		Expect(cf.Cf("push", golangAppName, "-p", assets.NewAssets().Golang, "--no-start").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("push", helloWorldAppName, "-p", assets.NewAssets().HelloWorld, "--no-start").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	AfterEach(func() {
		Expect(cf.Cf("delete", golangAppName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("delete", helloWorldAppName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	It("Copies over the package from the source app to the destination app", func() {
		Expect(cf.Cf("copy-source", helloWorldAppName, golangAppName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))

		Eventually(func() string {
			return helpers.CurlAppRoot(golangAppName)
		}, DEFAULT_TIMEOUT).Should(ContainSubstring("Hello, world!"))
	})
})
		Expect(cf.Cf("push", appName, "--no-start", "-b", config.RubyBuildpackName, "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().Dora, "-d", config.AppsDomain).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		app_helpers.SetBackend(appName)
		Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
	})

	AfterEach(func() {
		app_helpers.AppReport(appName, DEFAULT_TIMEOUT)

		Expect(cf.Cf("delete", appName, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	Describe("pushing", func() {
		It("makes the app reachable via its bound route", func() {
			Eventually(func() string {
				return helpers.CurlAppRoot(appName)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring("Hi, I'm Dora!"))
		})

		Describe("Context path", func() {
			var app2 string
			var path = "/imposter_dora"

			BeforeEach(func() {
				app2 = generator.PrefixedRandomName("CATS-APP-")
				Expect(cf.Cf("push", app2, "--no-start", "-b", config.RubyBuildpackName, "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().HelloWorld, "-d", config.AppsDomain).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
				app_helpers.SetBackend(app2)
				Expect(cf.Cf("start", app2).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
			})

			AfterEach(func() {
		var workerProcess Process
		processes := getProcess(appGuid, appName)
		for _, process := range processes {
			if process.Type == "web" {
				webProcess = process
			} else if process.Type == "worker" {
				workerProcess = process
			}
		}

		CreateAndMapRoute(appGuid, context.RegularUserContext().Space, helpers.LoadConfig().AppsDomain, webProcess.Name)

		StartApp(appGuid)

		Eventually(func() string {
			return helpers.CurlAppRoot(webProcess.Name)
		}, DEFAULT_TIMEOUT).Should(ContainSubstring("Hi, I'm Dora!"))

		output := helpers.CurlApp(webProcess.Name, "/env")
		Expect(output).To(ContainSubstring(fmt.Sprintf("application_name\\\":\\\"%s", appName)))
		Expect(output).To(ContainSubstring(appCreationEnvironmentVariables))

		Expect(cf.Cf("apps").Wait(DEFAULT_TIMEOUT)).To(Say(fmt.Sprintf("%s\\s+started", webProcess.Name)))
		Expect(cf.Cf("apps").Wait(DEFAULT_TIMEOUT)).To(Say(fmt.Sprintf("%s\\s+started", workerProcess.Name)))

		usageEvents := lastPageUsageEvents(appName)

		event1 := AppUsageEvent{Entity{ProcessType: webProcess.Type, AppGuid: webProcess.Guid, State: "STARTED", ParentAppGuid: appGuid, ParentAppName: appName}}
		event2 := AppUsageEvent{Entity{ProcessType: workerProcess.Type, AppGuid: workerProcess.Guid, State: "STARTED", ParentAppGuid: appGuid, ParentAppName: appName}}
		Expect(eventsInclude(usageEvents, event1)).To(BeTrue())
		Expect(eventsInclude(usageEvents, event2)).To(BeTrue())
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/app_helpers"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/random_name"
)

var _ = AppsDescribe("Delete Route", func() {
	var appName string

	BeforeEach(func() {
		appName = random_name.CATSRandomName("APP")

		Expect(cf.Cf("push", appName, "--no-start", "-b", Config.GetRubyBuildpackName(), "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().Dora, "-d", Config.GetAppsDomain()).Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
		app_helpers.SetBackend(appName)
		Expect(cf.Cf("start", appName).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
		Eventually(func() string {
			return helpers.CurlAppRoot(Config, appName)
		}, Config.DefaultTimeoutDuration()).Should(ContainSubstring("Hi, I'm Dora!"))
	})

	AfterEach(func() {
		app_helpers.AppReport(appName, Config.DefaultTimeoutDuration())

		Expect(cf.Cf("delete", appName, "-f", "-r").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
	})

	Describe("Removing the route", func() {
		It("Should be  able to remove and delete the route", func() {
			secondHost := random_name.CATSRandomName("ROUTE")

			By("adding a route")
			Eventually(cf.Cf("map-route", appName, Config.GetAppsDomain(), "-n", secondHost), Config.DefaultTimeoutDuration()).Should(Exit(0))
		BeforeEach(func() {
			dropletGuid := StageBuildpackPackage(packageGuid, Config.GetRubyBuildpackName())
			WaitForDropletToStage(dropletGuid)

			AssignDropletToApp(appGuid, dropletGuid)

			processes := GetProcesses(appGuid, appName)
			webProcess = GetProcessByType(processes, "web")

			CreateAndMapRoute(appGuid, TestSetup.RegularUserContext().Space, Config.GetAppsDomain(), webProcess.Name)

			StartApp(appGuid)

			Eventually(func() string {
				return helpers.CurlAppRoot(Config, webProcess.Name)
			}, Config.DefaultTimeoutDuration()).Should(ContainSubstring("Hi, I'm Dora!"))

			Expect(string(cf.Cf("apps").Wait(Config.DefaultTimeoutDuration()).Out.Contents())).To(MatchRegexp(fmt.Sprintf("(v3-)?(%s)*(-web)?(\\s)+(started)", webProcess.Name)))
		})

		Context("/v3/apps/:guid/processes/:type/instances/:index", func() {
			It("restarts the instance", func() {
				statsUrl := fmt.Sprintf("/v3/apps/%s/processes/web/stats", appGuid)

				By("ensuring the instance is running")
				statsBody := cf.Cf("curl", statsUrl).Wait(Config.DefaultTimeoutDuration()).Out.Contents()
				statsJSON := ProcessStats{}
				json.Unmarshal(statsBody, &statsJSON)
				Expect(statsJSON.Instance[0].State).To(Equal("RUNNING"))
		MapRouteToApp(domain, app2Path, app2)
		MapRouteToApp(domain, app3Path, app3)
	})

	AfterEach(func() {
		app_helpers.AppReport(app1, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app2, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app3, DEFAULT_TIMEOUT)

		DeleteApp(app1)
		DeleteApp(app2)
		DeleteApp(app3)
	})

	Context("when another app has a route with a context path", func() {
		It("routes to app with context path", func() {
			Eventually(func() string {
				return helpers.CurlAppRoot(domain)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app1))

			Eventually(func() string {
				return helpers.CurlApp(domain, app2Path)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app2))

			Eventually(func() string {
				return helpers.CurlApp(domain, app3Path)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app3))
		})
	})
})
		cf.Cf("curl", fmt.Sprintf("/v2/apps/%s/droplet/download", appGuid), "--output", app_droplet_path).Wait(Config.DefaultTimeoutDuration())

		cmd := exec.Command("tar", "-ztf", app_droplet_path)
		cmd.Stdout = &out
		err = cmd.Run()
		Expect(err).ToNot(HaveOccurred())

		Expect(out.String()).To(ContainSubstring("./app/config.ru"))
		Expect(out.String()).To(ContainSubstring("./tmp"))
		Expect(out.String()).To(ContainSubstring("./logs"))

		By("Pushing a different version of the app")

		Expect(cf.Cf("push", helloWorldAppName, "-p", assets.NewAssets().Dora).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
		Eventually(func() string {
			return helpers.CurlAppRoot(Config, helloWorldAppName)
		}, Config.DefaultTimeoutDuration()).Should(ContainSubstring("Hi, I'm Dora!"))

		By("Uploading the originally downloaded droplet of the app")

		token := v3_helpers.GetAuthToken()
		uploadUrl := fmt.Sprintf("%s%s/v2/apps/%s/droplet/upload", Config.Protocol(), Config.GetApiEndpoint(), appGuid)
		bits := fmt.Sprintf(`droplet=@%s`, app_droplet_path)
		curl := helpers.Curl(Config, "-v", uploadUrl, "-X", "PUT", "-F", bits, "-H", fmt.Sprintf("Authorization: %s", token)).Wait(Config.DefaultTimeoutDuration())
		Expect(curl).To(Exit(0))

		var job struct {
			Metadata struct {
				Url string `json:"url"`
			} `json:"metadata"`
		}
)

var _ = Describe("The Elasticsearch service", func() {

	Describe("adding elasticsearch to an app", func() {
		var (
			appName string
		)

		BeforeEach(func() {
			appName = generator.PrefixedRandomName("CATS-APP-")
			Expect(cf.Cf(
				"push", appName,
				"--no-start",
				"-b", config.GoBuildpackName,
				"-p", "../example_apps/es_test_app",
				"-d", config.AppsDomain,
			).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		})

		It("can be added to an app", func() {
			instanceName := generator.PrefixedRandomName("ES-SERVICE-")

			Expect(cf.Cf("create-service", "elasticsearch13", "free", instanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
			Expect(helpers.CurlAppRoot(appName)).To(ContainSubstring("You Know, for Search"))
		})
	})
})
		AfterEach(func() {
			DeleteApp(appName)
		})

		Context("when an app has multiple instances", func() {
			BeforeEach(func() {
				ScaleAppInstances(appName, 3)
			})

			Context("when the client does not send VCAP_ID and JSESSION cookies", func() {
				It("routes requests round robin to all instances", func() {
					var body string

					Eventually(func() string {
						body = helpers.CurlAppRoot(appName)
						return body
					}, DEFAULT_TIMEOUT).Should(ContainSubstring(fmt.Sprintf("Hello, %s", appName)))

					indexPre := parseInstanceIndex(body)

					Eventually(func() int {
						body := helpers.CurlAppRoot(appName)
						index := parseInstanceIndex(body)
						return index
					}, DEFAULT_TIMEOUT).ShouldNot(Equal(indexPre))
				})
			})
		})
	})
		hostname = app1
	})

	AfterEach(func() {
		helpers.AppReport(app1, Config.DefaultTimeoutDuration())

		helpers.DeleteApp(app1, Config.DefaultTimeoutDuration())
	})

	Context("when zipkin tracing is enabled", func() {
		Context("when zipkin headers are not in the request", func() {
			It("the sleuth error response has no error", func() {
				var curlOutput string
				// when req does not have headers
				Eventually(func() string {
					curlOutput = cf_helpers.CurlAppRoot(Config, hostname)
					return curlOutput
				}, Config.DefaultTimeoutDuration()).Should(ContainSubstring("parents:"))

				appLogsSession := cf.Cf("logs", "--recent", app1)

				Eventually(appLogsSession.Out, "5s").Should(gbytes.Say("x_b3_traceid"))
				_, _, parentSpanId := grabIDs(string(appLogsSession.Out.Contents()), "")

				Expect(parentSpanId).To(Equal("-"))

				By("when request has zipkin trace headers")

				traceId := "fee1f7ba6aeec41c"

				header1 := fmt.Sprintf(`X-B3-TraceId: %s `, traceId)
		MapRouteToApp(app2, domain, hostname, app2Path)
		MapRouteToApp(app3, domain, hostname, app3Path)
	})

	AfterEach(func() {
		app_helpers.AppReport(app1, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app2, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app3, DEFAULT_TIMEOUT)

		DeleteApp(app1)
		DeleteApp(app2)
		DeleteApp(app3)
	})

	Context("when another app has a route with a context path", func() {
		It("routes to app with context path", func() {
			Eventually(func() string {
				return helpers.CurlAppRoot(hostname)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app1))

			Eventually(func() string {
				return helpers.CurlApp(hostname, app2Path)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app2))

			Eventually(func() string {
				return helpers.CurlApp(hostname, app3Path)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app3))
		})
	})
})