Describe("Swap", func() {
		Context("when a new routing key arrives", func() {
			Context("when the routing key has both routes and endpoints", func() {
				BeforeEach(func() {
					tempTable := routing_table.NewTempTable(
						routing_table.RoutesByRoutingKey{key: routing_table.Routes{Hostnames: []string{hostname1, hostname2}, LogGuid: logGuid}},
						routing_table.EndpointsByRoutingKey{key: {endpoint1, endpoint2}},
					)

					messagesToEmit = table.Swap(tempTable)
				})

				It("emits registrations for each pairing", func() {
					expected := routing_table.MessagesToEmit{
						RegistrationMessages: []routing_table.RegistryMessage{
							routing_table.RegistryMessageFor(endpoint1, routing_table.Routes{Hostnames: []string{hostname1, hostname2}, LogGuid: logGuid}),
							routing_table.RegistryMessageFor(endpoint2, routing_table.Routes{Hostnames: []string{hostname1, hostname2}, LogGuid: logGuid}),
						},
					}
					Expect(messagesToEmit).To(MatchMessagesToEmit(expected))
				})
			})

			Context("when the process only has routes", func() {
				BeforeEach(func() {
					tempTable := routing_table.NewTempTable(
						routing_table.RoutesByRoutingKey{key: routing_table.Routes{Hostnames: []string{hostname1}, LogGuid: logGuid}},
						routing_table.EndpointsByRoutingKey{},
					)
					messagesToEmit = table.Swap(tempTable)
				})
		})

		It("unmarshals correctly", func() {
			message := routing_table.RegistryMessage{}

			err := json.Unmarshal([]byte(expectedJSON), &message)
			Expect(err).NotTo(HaveOccurred())
			Expect(message).To(Equal(expectedMessage))
		})
	})

	Describe("RegistryMessageFor", func() {
		It("creates a valid message from an endpoint and routes", func() {
			endpoint := routing_table.Endpoint{
				InstanceGuid:  "instance-guid",
				Host:          "1.1.1.1",
				Port:          61001,
				ContainerPort: 11,
			}
			routes := routing_table.Routes{
				Hostnames:       []string{"host-1.example.com", "host-2.example.com"},
				LogGuid:         "app-guid",
				RouteServiceUrl: "https://hello.com",
			}

			message := routing_table.RegistryMessageFor(endpoint, routes)
			Expect(message).To(Equal(expectedMessage))
		})
	})
})
			newEntry = &routing_table.RoutableEndpoints{
				Hostnames: map[string]struct{}{hostname1: struct{}{}},
				Endpoints: routing_table.EndpointsAsMap([]routing_table.Endpoint{endpoint1}),
			}
		})

		JustBeforeEach(func() {
			messages = builder.RegistrationsFor(existingEntry, newEntry)
		})

		Context("when no existing entry", func() {
			It("emits a registration", func() {
				expected := routing_table.MessagesToEmit{
					RegistrationMessages: []routing_table.RegistryMessage{
						routing_table.RegistryMessageFor(endpoint1, routing_table.Routes{Hostnames: []string{hostname1}}),
					},
				}
				Expect(messages).To(MatchMessagesToEmit(expected))
			})
		})

		Context("when new entry has no hostnames", func() {
			BeforeEach(func() {
				newEntry.Hostnames = make(map[string]struct{})
			})

			It("emits nothing", func() {
				Expect(messages).To(BeZero())
			})
		})
	BeforeEach(func() {
		eventSource = new(eventfakes.FakeEventSource)
		bbsClient = new(fake_bbs.FakeClient)
		bbsClient.SubscribeToEventsReturns(eventSource, nil)

		table = &fake_routing_table.FakeRoutingTable{}
		emitter = &fake_nats_emitter.FakeNATSEmitter{}
		syncEvents = syncer.Events{
			Sync: make(chan struct{}),
			Emit: make(chan struct{}),
		}
		logger = lagertest.NewTestLogger("test")

		dummyEndpoint := routing_table.Endpoint{InstanceGuid: expectedInstanceGuid, Host: expectedHost, Port: expectedContainerPort}
		dummyMessage := routing_table.RegistryMessageFor(dummyEndpoint, routing_table.Routes{Hostnames: []string{"foo.com", "bar.com"}, LogGuid: logGuid})
		dummyMessagesToEmit = routing_table.MessagesToEmit{
			RegistrationMessages: []routing_table.RegistryMessage{dummyMessage},
		}

		clock = fakeclock.NewFakeClock(time.Now())

		watcherProcess = watcher.NewWatcher(bbsClient, clock, table, emitter, syncEvents, logger)

		expectedRoutes = []string{"route-1", "route-2"}
		expectedCFRoute = cfroutes.CFRoute{Hostnames: expectedRoutes, Port: expectedContainerPort, RouteServiceUrl: expectedRouteServiceUrl}
		expectedRoutingKey = routing_table.RoutingKey{
			ProcessGuid:   expectedProcessGuid,
			ContainerPort: expectedContainerPort,
		}
		routerStartMessages = startMessages

		natsClient.WhenSubscribing("router.start", func(callback nats.MsgHandler) error {
			go func() {
				for msg := range startMessages {
					callback(msg)
				}
			}()

			return nil
		})

		//what follows is fake data to distinguish between
		//the "sync" and "emit" codepaths
		dummyEndpoint := routing_table.Endpoint{InstanceGuid: "instance-guid-1", Host: "1.1.1.1", Port: 11, ContainerPort: 1111}
		dummyMessage := routing_table.RegistryMessageFor(dummyEndpoint, routing_table.Routes{Hostnames: []string{"foo.com", "bar.com"}, LogGuid: logGuid})
		syncMessages = routing_table.MessagesToEmit{
			RegistrationMessages: []routing_table.RegistryMessage{dummyMessage},
		}

		dummyEndpoint = routing_table.Endpoint{InstanceGuid: "instance-guid-2", Host: "2.2.2.2", Port: 22, ContainerPort: 2222}
		dummyMessage = routing_table.RegistryMessageFor(dummyEndpoint, routing_table.Routes{Hostnames: []string{"baz.com"}, LogGuid: logGuid})
		messagesToEmit = routing_table.MessagesToEmit{
			RegistrationMessages: []routing_table.RegistryMessage{dummyMessage},
		}

		schedulingInfoResponse = &models.DesiredLRPSchedulingInfo{
			DesiredLRPKey: models.NewDesiredLRPKey(processGuid, "domain", logGuid),
			Routes:        cfroutes.CFRoutes{{Hostnames: []string{"route-1", "route-2"}, Port: containerPort}}.RoutingInfo(),
		}