git.dev.gkxim.com/golang-packages/geobed@v0.0.0-20190708072815-e989ac62624a/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  }