github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/route_helpers/route_helpers_test.go (about)

     1  package route_helpers_test
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	. "github.com/onsi/ginkgo"
     7  	. "github.com/onsi/gomega"
     8  
     9  	"github.com/cloudfoundry-incubator/ltc/route_helpers"
    10  	. "github.com/cloudfoundry-incubator/ltc/test_helpers/matchers"
    11  	"github.com/cloudfoundry-incubator/receptor"
    12  )
    13  
    14  var _ = Describe("RoutingInfoHelpers", func() {
    15  	var (
    16  		appRoute1 route_helpers.AppRoute
    17  		appRoute2 route_helpers.AppRoute
    18  		appRoute3 route_helpers.AppRoute
    19  
    20  		appRoutes route_helpers.AppRoutes
    21  	)
    22  
    23  	BeforeEach(func() {
    24  		appRoute1 = route_helpers.AppRoute{
    25  			Hostnames: []string{"foo1.example.com", "bar1.examaple.com"},
    26  			Port:      11111,
    27  		}
    28  		appRoute2 = route_helpers.AppRoute{
    29  			Hostnames: []string{"foo2.example.com", "bar2.examaple.com"},
    30  			Port:      22222,
    31  		}
    32  		appRoute3 = route_helpers.AppRoute{
    33  			Hostnames: []string{"foo3.example.com", "bar3.examaple.com"},
    34  			Port:      33333,
    35  		}
    36  
    37  		appRoutes = route_helpers.AppRoutes{appRoute1, appRoute2, appRoute3}
    38  	})
    39  
    40  	Describe("AppRoutes", func() {
    41  		Describe("RoutingInfo", func() {
    42  			var routingInfo receptor.RoutingInfo
    43  
    44  			JustBeforeEach(func() {
    45  				routingInfo = appRoutes.RoutingInfo()
    46  			})
    47  
    48  			It("maps the serialized routes to the correct key", func() {
    49  				expectedBytes := []byte(`[{"hostnames":["foo1.example.com","bar1.examaple.com"],"port":11111},{"hostnames":["foo2.example.com","bar2.examaple.com"],"port":22222},{"hostnames":["foo3.example.com","bar3.examaple.com"],"port":33333}]`)
    50  				Expect(appRoutes.RoutingInfo()["cf-router"].MarshalJSON()).To(MatchJSON(expectedBytes))
    51  			})
    52  
    53  			Context("when AppRoutes is empty", func() {
    54  				BeforeEach(func() {
    55  					appRoutes = route_helpers.AppRoutes{}
    56  				})
    57  
    58  				It("marshals an empty list", func() {
    59  					payload, err := routingInfo["cf-router"].MarshalJSON()
    60  					Expect(err).NotTo(HaveOccurred())
    61  
    62  					Expect(payload).To(MatchJSON(`[]`))
    63  				})
    64  			})
    65  		})
    66  	})
    67  
    68  	Describe("AppRoutesFromRoutingInfo", func() {
    69  		var routingInfo receptor.RoutingInfo
    70  
    71  		Context("when the method returns a value", func() {
    72  			var routesResult route_helpers.AppRoutes
    73  
    74  			JustBeforeEach(func() {
    75  				routesResult = route_helpers.AppRoutesFromRoutingInfo(routingInfo)
    76  			})
    77  
    78  			Context("when lattice app routes are present in the routing info", func() {
    79  				BeforeEach(func() {
    80  					routingInfo = appRoutes.RoutingInfo()
    81  				})
    82  
    83  				It("returns the routes", func() {
    84  					Expect(appRoutes).To(Equal(routesResult))
    85  				})
    86  			})
    87  
    88  			Context("when the result should be nil", func() {
    89  				itReturnsNilRoutes := func() {
    90  					It("returns nil routes", func() {
    91  						Expect(routesResult).To(BeNil())
    92  					})
    93  				}
    94  
    95  				Context("when the lattice routes are nil", func() {
    96  					BeforeEach(func() {
    97  						routingInfo = receptor.RoutingInfo{route_helpers.AppRouter: nil}
    98  					})
    99  
   100  					itReturnsNilRoutes()
   101  				})
   102  
   103  				Context("when lattice app routes are not present in the routing info", func() {
   104  					BeforeEach(func() {
   105  						routingInfo = receptor.RoutingInfo{}
   106  					})
   107  
   108  					itReturnsNilRoutes()
   109  				})
   110  
   111  				Context("when the routing info is nil", func() {
   112  					BeforeEach(func() {
   113  						routingInfo = nil
   114  					})
   115  
   116  					itReturnsNilRoutes()
   117  				})
   118  			})
   119  		})
   120  
   121  		Context("when the json.RawMessage is malformed", func() {
   122  			BeforeEach(func() {
   123  				routingInfo = receptor.RoutingInfo{}
   124  				jsonMessage := json.RawMessage(`{"what": "up`)
   125  				routingInfo[route_helpers.AppRouter] = &jsonMessage
   126  			})
   127  
   128  			It("panics at the disco", func() {
   129  				appRoutesFromRoutingInfo := func() func() {
   130  					return func() { route_helpers.AppRoutesFromRoutingInfo(routingInfo) }
   131  				}
   132  
   133  				Consistently(appRoutesFromRoutingInfo).Should(Panic(), "invalid json.RawMessage ought to panic")
   134  			})
   135  		})
   136  	})
   137  
   138  	Describe("HostnamesByPort", func() {
   139  		It("returns map of ports to slice of hostnames", func() {
   140  			expectedHostnamesByPort := map[uint16][]string{
   141  				11111: []string{"foo1.example.com", "bar1.examaple.com"},
   142  				22222: []string{"foo2.example.com", "bar2.examaple.com"},
   143  				33333: []string{"foo3.example.com", "bar3.examaple.com"},
   144  			}
   145  
   146  			Expect(appRoutes.HostnamesByPort()).To(Equal(expectedHostnamesByPort))
   147  		})
   148  	})
   149  
   150  	Describe("Routes", func() {
   151  
   152  		var (
   153  			routes               route_helpers.Routes
   154  			tcpRoute1, tcpRoute2 route_helpers.TcpRoute
   155  			diegoSSHRoute        *route_helpers.DiegoSSHRoute
   156  		)
   157  
   158  		BeforeEach(func() {
   159  			tcpRoute1 = route_helpers.TcpRoute{
   160  				RouterGroupGuid: route_helpers.DefaultRouterGroupGuid,
   161  				ExternalPort:    50000,
   162  				Port:            5222,
   163  			}
   164  			tcpRoute2 = route_helpers.TcpRoute{
   165  				RouterGroupGuid: route_helpers.DefaultRouterGroupGuid,
   166  				ExternalPort:    51000,
   167  				Port:            5223,
   168  			}
   169  			diegoSSHRoute = &route_helpers.DiegoSSHRoute{
   170  				Port:       2222,
   171  				PrivateKey: "ssshhhhh",
   172  			}
   173  			routes = route_helpers.Routes{
   174  				AppRoutes: route_helpers.AppRoutes{
   175  					appRoute1, appRoute2,
   176  				},
   177  				TcpRoutes: route_helpers.TcpRoutes{
   178  					tcpRoute1, tcpRoute2,
   179  				},
   180  				DiegoSSHRoute: diegoSSHRoute,
   181  			}
   182  		})
   183  
   184  		Describe("RoutingInfo", func() {
   185  			var routingInfo receptor.RoutingInfo
   186  
   187  			JustBeforeEach(func() {
   188  				routingInfo = routes.RoutingInfo()
   189  			})
   190  
   191  			It("wraps the serialized routes with the correct key", func() {
   192  				expectedAppRoutes, err := json.Marshal(route_helpers.AppRoutes{appRoute1, appRoute2})
   193  				Expect(err).NotTo(HaveOccurred())
   194  
   195  				appRoutesPayload, err := routingInfo[route_helpers.AppRouter].MarshalJSON()
   196  				Expect(err).NotTo(HaveOccurred())
   197  
   198  				Expect(appRoutesPayload).To(MatchJSON(expectedAppRoutes))
   199  
   200  				expectedTcpRoutes, err := json.Marshal(route_helpers.TcpRoutes{tcpRoute1, tcpRoute2})
   201  				Expect(err).NotTo(HaveOccurred())
   202  
   203  				tcpRoutesPayload, err := routingInfo[route_helpers.TcpRouter].MarshalJSON()
   204  				Expect(err).NotTo(HaveOccurred())
   205  
   206  				Expect(tcpRoutesPayload).To(MatchJSON(expectedTcpRoutes))
   207  
   208  				expectedBytes := []byte(`{"container_port":2222,"private_key":"ssshhhhh"}`)
   209  				Expect(routingInfo["diego-ssh"].MarshalJSON()).To(MatchJSON(expectedBytes))
   210  			})
   211  
   212  			Context("when Routes is empty", func() {
   213  				BeforeEach(func() {
   214  					routes = route_helpers.Routes{
   215  						AppRoutes: route_helpers.AppRoutes{},
   216  						TcpRoutes: route_helpers.TcpRoutes{},
   217  					}
   218  				})
   219  
   220  				It("marshals an empty list", func() {
   221  					appRoutesPayload, err := routingInfo[route_helpers.AppRouter].MarshalJSON()
   222  					Expect(err).NotTo(HaveOccurred())
   223  					Expect(appRoutesPayload).To(MatchJSON("[]"))
   224  
   225  					tcpRoutesPayload, err := routingInfo[route_helpers.TcpRouter].MarshalJSON()
   226  					Expect(err).NotTo(HaveOccurred())
   227  					Expect(tcpRoutesPayload).To(MatchJSON("[]"))
   228  				})
   229  			})
   230  		})
   231  
   232  		Describe("RoutesFromRoutingInfo", func() {
   233  			var routingInfo receptor.RoutingInfo
   234  
   235  			Context("when the method returns a value", func() {
   236  				var routesResult route_helpers.Routes
   237  
   238  				JustBeforeEach(func() {
   239  					routesResult = route_helpers.RoutesFromRoutingInfo(routingInfo)
   240  				})
   241  
   242  				Context("when lattice app routes are present in the routing info", func() {
   243  					BeforeEach(func() {
   244  						routingInfo = routes.RoutingInfo()
   245  					})
   246  
   247  					It("returns the routes", func() {
   248  						Expect(routesResult).To(Equal(routes))
   249  					})
   250  				})
   251  
   252  				Context("when the result should be nil", func() {
   253  					itReturnsEmptyRoutes := func() {
   254  						It("returns nil routes", func() {
   255  							Expect(routesResult).To(BeZero())
   256  						})
   257  					}
   258  
   259  					Context("when the both http and tcp routes are nil", func() {
   260  						BeforeEach(func() {
   261  							routingInfo = receptor.RoutingInfo{
   262  								route_helpers.AppRouter: nil,
   263  								route_helpers.TcpRouter: nil,
   264  							}
   265  						})
   266  
   267  						itReturnsEmptyRoutes()
   268  					})
   269  
   270  					Context("when lattice app and tcp routes are not present in the routing info", func() {
   271  						BeforeEach(func() {
   272  							routingInfo = receptor.RoutingInfo{}
   273  						})
   274  
   275  						itReturnsEmptyRoutes()
   276  					})
   277  
   278  					Context("when the routing info is nil", func() {
   279  						BeforeEach(func() {
   280  							routingInfo = nil
   281  						})
   282  
   283  						itReturnsEmptyRoutes()
   284  					})
   285  
   286  					Context("when the http routes are nil", func() {
   287  						var onlyTcpRoutes route_helpers.Routes
   288  						BeforeEach(func() {
   289  							onlyTcpRoutes = route_helpers.Routes{
   290  								TcpRoutes: route_helpers.TcpRoutes{tcpRoute1},
   291  							}
   292  							routingInfo = onlyTcpRoutes.RoutingInfo()
   293  						})
   294  
   295  						It("returns only tcp routes", func() {
   296  							Expect(routesResult).To(Equal(onlyTcpRoutes))
   297  						})
   298  					})
   299  
   300  					Context("when the tcp routes are nil", func() {
   301  						var onlyHttpRoutes route_helpers.Routes
   302  						BeforeEach(func() {
   303  							onlyHttpRoutes = route_helpers.Routes{
   304  								AppRoutes: route_helpers.AppRoutes{appRoute1},
   305  							}
   306  							routingInfo = onlyHttpRoutes.RoutingInfo()
   307  						})
   308  
   309  						It("returns only http routes", func() {
   310  							Expect(routesResult).To(Equal(onlyHttpRoutes))
   311  						})
   312  					})
   313  				})
   314  			})
   315  
   316  			Context("when the json.RawMessage is malformed", func() {
   317  				BeforeEach(func() {
   318  					routingInfo = receptor.RoutingInfo{}
   319  					jsonMessage := json.RawMessage(`{"what": "up`)
   320  					routingInfo[route_helpers.TcpRouter] = &jsonMessage
   321  				})
   322  
   323  				It("panics", func() {
   324  					routesFromRoutingInfo := func() func() {
   325  						return func() { route_helpers.RoutesFromRoutingInfo(routingInfo) }
   326  					}
   327  					Consistently(routesFromRoutingInfo).Should(Panic(), "invalid json.RawMessage ought to panic")
   328  				})
   329  			})
   330  		})
   331  	})
   332  
   333  	Describe("GetPrimaryPort", func() {
   334  		Context("when there is no monitor port, but exposedPorts are empty", func() {
   335  			It("return 0", func() {
   336  				returnPort := route_helpers.GetPrimaryPort(uint16(0), []uint16{})
   337  				Expect(returnPort).To(BeZero())
   338  			})
   339  		})
   340  
   341  		Context("when there is monitor port, and exposedPorts are not empty", func() {
   342  			It("return the first exposed port", func() {
   343  				returnPort := route_helpers.GetPrimaryPort(uint16(0), []uint16{2000, 3000})
   344  				Expect(returnPort).To(Equal(uint16(2000)))
   345  			})
   346  		})
   347  
   348  		Context("when there is monitor port", func() {
   349  			It("return the monitor port", func() {
   350  				returnPort := route_helpers.GetPrimaryPort(uint16(1000), []uint16{2000, 3000})
   351  				Expect(returnPort).To(Equal(uint16(1000)))
   352  			})
   353  		})
   354  
   355  		Context("when there is monitor port, and the exposedPorts is empty", func() {
   356  			It("return the monitor port", func() {
   357  				returnPort := route_helpers.GetPrimaryPort(uint16(1000), []uint16{})
   358  				Expect(returnPort).To(Equal(uint16(1000)))
   359  			})
   360  		})
   361  	})
   362  
   363  	Describe("BuildDefaultRoutingInfo", func() {
   364  		Context("when no exposedPorts is given", func() {
   365  			It("output empty approutes", func() {
   366  				appRoutes := route_helpers.BuildDefaultRoutingInfo("cool-app", []uint16{}, 5000, "cool-app-domain")
   367  				Expect(appRoutes).To(BeEmpty())
   368  			})
   369  		})
   370  
   371  		Context("when primaryPort is not included in the exposedPorts", func() {
   372  			It("doesn't output the default route", func() {
   373  				expectedAppRoutes := route_helpers.AppRoutes{
   374  					{Hostnames: []string{"cool-app-2000.cool-app-domain"}, Port: 2000},
   375  				}
   376  				appRoutes := route_helpers.BuildDefaultRoutingInfo("cool-app", []uint16{2000}, 5000, "cool-app-domain")
   377  				Expect(appRoutes).To(Equal(expectedAppRoutes))
   378  			})
   379  		})
   380  
   381  		Context("when primaryPort is included in the exposedPorts", func() {
   382  			It("outputs a default route with primary port in addition to the default route", func() {
   383  				expectedAppRoutes := route_helpers.AppRoutes{
   384  					{Hostnames: []string{"cool-app-2000.cool-app-domain"}, Port: 2000},
   385  					{Hostnames: []string{"cool-app.cool-app-domain", "cool-app-5000.cool-app-domain"}, Port: 5000},
   386  				}
   387  				appRoutes := route_helpers.BuildDefaultRoutingInfo("cool-app", []uint16{5000, 2000}, 5000, "cool-app-domain")
   388  				Expect(appRoutes).Should(ContainExactly(expectedAppRoutes))
   389  			})
   390  		})
   391  	})
   392  })