github.com/SocialHarvest/geobed@v0.0.0-20150910163054-28007bbd415f/geobed_test.go (about) 1 package geobed 2 3 import ( 4 . "gopkg.in/check.v1" 5 "testing" 6 ) 7 8 // Hook up gocheck into the "go test" runner. 9 func Test(t *testing.T) { TestingT(t) } 10 11 type GeobedSuite struct { 12 testLocations []map[string]string 13 } 14 15 var _ = Suite(&GeobedSuite{}) 16 17 var g GeoBed 18 19 func (s *GeobedSuite) SetUpSuite(c *C) { 20 // This is a common alternate name. However, there's a city called "Apple" (at least one). So it's a bit difficult. 21 // Plus many people would put "The Big Apple" ... Yet Geonames alt city names has just "Big Apple" ... It may be worth trying to improve this though. 22 //s.testLocations = append(s.testLocations, map[string]string{"query": "Big Apple", "city": "New York City", "country": "US", "region": "NY"}) 23 24 //s.testLocations = append(s.testLocations, map[string]string{"query": "NYC", "city": "New York City", "country": "US", "region": "NY"}) 25 26 s.testLocations = append(s.testLocations, map[string]string{"query": "New York, NY", "city": "New York", "country": "US", "region": "NY"}) 27 s.testLocations = append(s.testLocations, map[string]string{"query": "New York", "city": "New York City", "country": "US", "region": "NY"}) 28 s.testLocations = append(s.testLocations, map[string]string{"query": "Austin Tx", "city": "Austin", "country": "US", "region": "TX"}) 29 s.testLocations = append(s.testLocations, map[string]string{"query": "tx austin", "city": "Austin", "country": "US", "region": "TX"}) 30 s.testLocations = append(s.testLocations, map[string]string{"query": "Paris, TX", "city": "Paris", "country": "US", "region": "TX"}) 31 s.testLocations = append(s.testLocations, map[string]string{"query": "New Paris, IN", "city": "New Paris", "country": "US", "region": "IN"}) 32 //s.testLocations = append(s.testLocations, map[string]string{"query": "Sweden, Stockholm", "city": "Stockholm Center", "country": "SE", "region": "26"}) 33 //s.testLocations = append(s.testLocations, map[string]string{"query": "Stockholm", "city": "Stockholm", "country": "SE", "region": "26"}) 34 s.testLocations = append(s.testLocations, map[string]string{"query": "Newport Beach, Orange County ", "city": "Newport Beach", "country": "US", "region": "CA"}) 35 s.testLocations = append(s.testLocations, map[string]string{"query": "Newport Beach", "city": "Newport Beach", "country": "US", "region": "CA"}) 36 s.testLocations = append(s.testLocations, map[string]string{"query": "london", "city": "London", "country": "GB", "region": ""}) 37 s.testLocations = append(s.testLocations, map[string]string{"query": "Paris", "city": "Paris", "country": "FR", "region": "A8"}) 38 //s.testLocations = append(s.testLocations, map[string]string{"query": "New Paris", "city": "New Paris", "country": "US", "region": "IN"}) 39 40 // Often, "AUS" ends up mapping to Austria. 41 // In our case here, Ausa is a city in India. That's a logical match for "AUS" ... 42 // Airport codes are tricky. Most geocoding don't hangle them properly/reliably anyway. 43 //s.testLocations = append(s.testLocations, map[string]string{"query": "SFO", "city": "San Francisco", "country": "US", "region": "CA"}) 44 //s.testLocations = append(s.testLocations, map[string]string{"query": "AUS", "city": "Austin", "country": "US", "region": "TX"}) 45 46 // Will test out of range on the slice when looking up (0 end) 47 s.testLocations = append(s.testLocations, map[string]string{"query": "ਪੈਰਿਸ", "city": "'Aade\xefssa", "country": "SY", "region": "03"}) 48 } 49 50 func (s *GeobedSuite) TestANewGeobed(c *C) { 51 g = NewGeobed() 52 c.Assert(len(g.c), Not(Equals), 0) 53 c.Assert(len(g.co), Not(Equals), 0) 54 c.Assert(len(cityNameIdx), Not(Equals), 0) 55 c.Assert(g.c, FitsTypeOf, []GeobedCity(nil)) 56 c.Assert(g.co, FitsTypeOf, []CountryInfo(nil)) 57 c.Assert(cityNameIdx, FitsTypeOf, make(map[string]int)) 58 } 59 60 func (s *GeobedSuite) TestGeocode(c *C) { 61 //g := NewGeobed() 62 for _, v := range s.testLocations { 63 r := g.Geocode(v["query"]) 64 c.Assert(r.City, Equals, v["city"]) 65 c.Assert(r.Country, Equals, v["country"]) 66 // Due to all the data and various sets, the region can be a little weird. It's intended to be US state first and foremost (where it is most helpful in geocoding). 67 // TODO: Look back into this later and try to make sense of it all. It may end up needing to be multiple fields (which will further complicate the matching). 68 if v["region"] != "" { 69 c.Assert(r.Region, Equals, v["region"]) 70 } 71 } 72 73 r := g.Geocode("") 74 c.Assert(r.City, Equals, "") 75 76 r = g.Geocode(" ") 77 c.Assert(r.Population, Equals, int32(0)) 78 } 79 80 func (s *GeobedSuite) TestReverseGeocode(c *C) { 81 //g := NewGeobed() 82 83 r := g.ReverseGeocode(30.26715, -97.74306) 84 c.Assert(r.City, Equals, "Austin") 85 c.Assert(r.Region, Equals, "TX") 86 c.Assert(r.Country, Equals, "US") 87 88 r = g.ReverseGeocode(37.44651, -122.15322) 89 c.Assert(r.City, Equals, "Palo Alto") 90 c.Assert(r.Region, Equals, "CA") 91 c.Assert(r.Country, Equals, "US") 92 93 r = g.ReverseGeocode(37, -122) 94 c.Assert(r.City, Equals, "Santa Cruz") 95 96 r = g.ReverseGeocode(37.44, -122.15) 97 c.Assert(r.City, Equals, "Stanford") 98 99 r = g.ReverseGeocode(51.51279, -0.09184) 100 c.Assert(r.City, Equals, "City of London") 101 } 102 103 func (s *GeobedSuite) TestNext(c *C) { 104 c.Assert(string(prev(rune("new york"[0]))), Equals, "m") 105 c.Assert(prev(rune("new york"[0])), Equals, int32(109)) 106 } 107 108 func (s *GeobedSuite) TestToUpper(c *C) { 109 c.Assert(toUpper("nyc"), Equals, "NYC") 110 } 111 112 func (s *GeobedSuite) TestToLower(c *C) { 113 c.Assert(toLower("NYC"), Equals, "nyc") 114 } 115 116 // Benchmark comments from a MacbookPro Retina with 8GB of RAM with who knows what running. 117 118 // 5629888699 ns/op 119 // 5336288337 ns/op 120 // 5473618388 ns/op 121 // This takes about 5 seconds (to load the data sets into memory - should only happen once per application, ideally one would do this up front) 122 func BenchmarkNewGeobed(b *testing.B) { 123 g = NewGeobed() 124 } 125 126 // 2285549904 ns/op 127 // 2393945317 ns/op 128 // 2214503806 ns/op 129 // 2265304148 ns/op 130 // 2186608767 ns/op 131 // This has been scoring around 2 - 2.4 seconds on my MacbookPro Retina with 8GB of RAM (before concurrency was added) 132 // (20) 98841134 ns/op 133 func BenchmarkReverseGeocode(b *testing.B) { 134 for n := 0; n < b.N; n++ { 135 //g.ReverseGeocode(37.44651, -122.15322) 136 g.ReverseGeocode(51.51279, -0.09184) 137 } 138 } 139 140 // 141 // Before indexing the slice keys, it would take 2.8 - 3 seconds per lookup. 142 // 2968170541 ns/op 143 // 2956824815 ns/op 144 // 2861628023 ns/op 145 // 146 // After using the index and ranging over sections of the slice, it takes about 0.0175 - 0.02 seconds per lookup! 147 // (10) 175591906 ns/op 148 // (10) 180395494 ns/op 149 // (10) 123880439 ns/op 150 // (10) 124857396 ns/op 151 // (10) 164229982 ns/op (for Austin, TX) - speed can change a tiny bit based on what's being searched and where it is in the index, how items that start with the same characters, etc. 152 // (10) 135527499 ns/op 153 func BenchmarkGeocode(b *testing.B) { 154 155 for n := 0; n < b.N; n++ { 156 g.Geocode("New York") 157 } 158 }