def test_cell(self): session = self.db_slave_session cell_key = { 'radio': RADIO_TYPE['gsm'], 'mcc': GB_MCC, 'mnc': 1, 'lac': 1, } session.add(Cell( lat=GB_LAT, lon=GB_LON, range=6000, cid=1, **cell_key)) session.add(Cell( lat=GB_LAT, lon=GB_LON, range=9000, cid=CELLID_LAC, **cell_key)) session.flush() result = locate.search_all_sources( session, 'm', {'cell': [dict(cid=1, **cell_key)]}, client_addr=GB_IP, geoip_db=self.geoip_db, api_key_log=True, api_key_name='test') self.assertEqual(result, {'lat': GB_LAT, 'lon': GB_LON, 'accuracy': 6000}) self.check_stats( counter=[ 'm.cell_found', 'm.cell_hit', 'm.cell_lac_found', 'm.api_log.test.cell_hit', ], )
def test_cell_ignore_invalid_lac_cid(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) ignored_key = dict(mcc=1, mnc=2, lac=-1, cid=-1) data = [ Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), Cell(lat=10000000, lon=10000000, radio=2, **ignored_key), Cell(lat=10020000, lon=10040000, radio=3, **ignored_key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/search?key=test', {"radio": "gsm", "cell": [ dict(radio="umts", cid=4, **key), dict(radio="umts", cid=5, **key), dict(radio="umts", cid=5, mcc=1, mnc=2, lac=-1), dict(radio="umts", cid=-1, mcc=1, mnc=2, lac=3), ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"status": "ok", "lat": 1.0010000, "lon": 1.0020000, "accuracy": 35000})
def test_lac_miss(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) data = [ Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), Cell(lat=10060000, lon=10060000, radio=2, cid=6, **key), Cell(lat=10026666, lon=10033333, radio=2, cid=CELLID_LAC, range=50000, **key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/geolocate?key=test', {'radioType': 'wcdma', 'cellTowers': [ {'cellId': 5, 'mobileCountryCode': 1, 'mobileNetworkCode': 2, 'locationAreaCode': 4}]}, status=404) self.assertEqual( res.json, {"error": { "errors": [{ "domain": "geolocation", "reason": "notFound", "message": "Not found", }], "code": 404, "message": "Not found" }} )
def test_cell_miss_lac_hit(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) umts = RADIO_TYPE['umts'] data = [ Cell(lat=lat, lon=lon, radio=umts, cid=4, **key), Cell(lat=lat + 0.002, lon=lon + 0.004, radio=umts, cid=5, **key), Cell(lat=lat + 0.006, lon=lon + 0.006, radio=umts, cid=6, **key), Cell(lat=lat + 0.0026666, lon=lon + 0.0033333, radio=umts, cid=CELLID_LAC, range=500000, **key), ] session.add_all(data) session.flush() result = locate.search_all_sources( session, 'm', {"cell": [dict(radio="umts", cid=7, **key)]}, api_key_log=True, api_key_name='test') self.assertEqual(result, {'lat': PARIS_LAT + 0.0026666, 'lon': PARIS_LON + 0.0033333, 'accuracy': 500000}) self.check_stats( counter=[ 'm.no_cell_found', 'm.cell_lac_found', 'm.cell_lac_hit', 'm.api_log.test.cell_lac_hit', ], )
def test_cell_miss_lac_hit(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) umts = RADIO_TYPE['umts'] data = [ Cell(lat=lat, lon=lon, radio=umts, cid=4, **key), Cell(lat=lat + 0.002, lon=lon + 0.004, radio=umts, cid=5, **key), Cell(lat=lat + 0.006, lon=lon + 0.006, radio=umts, cid=6, **key), CellArea(lat=lat + 0.0026666, lon=lon + 0.0033333, radio=umts, range=500000, **key), ] session.add_all(data) session.flush() result = self._make_query( data={"cell": [dict(radio="umts", cid=7, **key)]}, api_key_log=True) self.assertEqual(result, {'lat': PARIS_LAT + 0.0026666, 'lon': PARIS_LON + 0.0033333, 'accuracy': 500000}) self.check_stats( counter=[ 'm.cell_lac_hit', 'm.api_log.test.cell_lac_hit', ('m.api_log.test.cell_hit', 0), ('m.api_log.test.cell_miss', 0), ], )
def test_cell_hit_ignores_lac(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) data = [ Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), Cell(lat=10060000, lon=10060000, radio=2, cid=6, **key), Cell(lat=10026666, lon=10033333, radio=2, cid=CELLID_LAC, range=50000, **key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/geolocate?key=test', {'radioType': 'wcdma', 'cellTowers': [ {'cellId': 5, 'mobileCountryCode': 1, 'mobileNetworkCode': 2, 'locationAreaCode': 3}]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {'location': {"lat": 1.0020000, "lng": 1.0040000}, "accuracy": 35000.0})
def test_cell_multiple_lac_lower_range_wins(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON gsm = RADIO_TYPE['gsm'] key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) key2 = dict(mcc=FRANCE_MCC, mnc=2, lac=4) data = [ Cell(lat=lat + 0.2, lon=lon + 0.2, radio=gsm, cid=CELLID_LAC, range=10000, **key), Cell(lat=lat + 0.2, lon=lon + 0.4, radio=gsm, cid=4, range=4000, **key), Cell(lat=lat, lon=lon, radio=gsm, cid=CELLID_LAC, range=20000, **key2), Cell(lat=lat + 0.02, lon=lon + 0.02, radio=gsm, cid=4, range=2000, **key2), ] session.add_all(data) session.flush() # We have two lacs with each one known cell. # The lac with the smallest cell wins. result = locate.search_all_sources( session, 'm', {"cell": [ dict(radio="gsm", cid=4, **key), dict(radio="gsm", cid=4, **key2), ]}) self.assertEqual(result, {'lat': PARIS_LAT + 0.02, 'lon': PARIS_LON + 0.02, 'accuracy': CELL_MIN_ACCURACY})
def test_cell_hit_ignores_lac(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) data = [ Cell(lat=lat, lon=lon, range=1000, radio=2, cid=4, **key), Cell(lat=lat + 0.002, lon=lon + 0.004, range=1000, radio=2, cid=5, **key), Cell(lat=lat + 0.006, lon=lon + 0.006, range=1000, radio=2, cid=6, **key), CellArea(lat=lat + 0.0026666, lon=lon + 0.0033333, radio=2, range=50000, **key), ] session.add_all(data) session.flush() result = self._make_query( data={"cell": [dict(radio="umts", cid=5, **key)]}) self.assertEqual(result, {'lat': PARIS_LAT + 0.002, 'lon': PARIS_LON + 0.004, 'accuracy': CELL_MIN_ACCURACY})
def test_wifi_not_found_cell_fallback(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON umts = RADIO_TYPE['umts'] key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) data = [ Wifi(key="a0a0a0a0a0a0", lat=3, lon=3), Cell(lat=lat, lon=lon, radio=umts, cid=4, **key), Cell(lat=lat + 0.002, lon=lon + 0.004, radio=umts, cid=5, **key), ] session.add_all(data) session.flush() result = locate.search_all_sources( session, 'm', {"cell": [ dict(radio="umts", cid=4, **key), dict(radio="umts", cid=5, **key), ], "wifi": [{"key": "101010101010"}, {"key": "202020202020"}]}) self.assertEqual(result, {'lat': PARIS_LAT + 0.001, 'lon': PARIS_LON + 0.002, 'accuracy': CELL_MIN_ACCURACY})
def test_cell_multiple_radio_mixed_cell_lac_hit(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON gsm = RADIO_TYPE['gsm'] lte = RADIO_TYPE['lte'] key = dict(mcc=FRANCE_MCC, mnc=3, lac=4) key2 = dict(mcc=FRANCE_MCC, mnc=2, lac=3) data = [ Cell(lat=lat + 0.2, lon=lon + 0.2, radio=gsm, cid=CELLID_LAC, range=3000, **key), Cell(lat=lat + 0.2, lon=lon + 0.4, radio=gsm, cid=5, range=500, **key), Cell(lat=lat, lon=lon, radio=lte, cid=CELLID_LAC, range=10000, **key2), Cell(lat=lat + 0.01, lon=lon + 0.02, radio=lte, cid=4, range=2000, **key2), ] session.add_all(data) session.flush() # GSM lac-only hit (cid 9 instead of 5) and a LTE cell hit result = locate.search_all_sources( session, 'm', {"cell": [ dict(radio="gsm", cid=9, **key), dict(radio="lte", cid=4, **key2), ]}) self.assertEqual(result, {'lat': PARIS_LAT + 0.01, 'lon': PARIS_LON + 0.02, 'accuracy': CELL_MIN_ACCURACY})
def test_ok_cell(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) data = [ Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/search?key=test', {"radio": "gsm", "cell": [ dict(radio="umts", cid=4, **key), dict(radio="umts", cid=5, **key), ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"status": "ok", "lat": 1.0010000, "lon": 1.0020000, "accuracy": 35000}) self.check_expected_heka_messages( total=4, timer=[('http.request', {'url_path': '/v1/search'})], counter=[('search.api_key.test', 1), ('search.cell_hit', 1), ('http.request', 1)] )
def test_cell_multiple_country_codes_from_mcc(self): session = self.db_slave_session cell_key = { 'radio': RADIO_TYPE['gsm'], 'mcc': GB_MCC, 'mnc': 1, 'lac': 1, } session.add(Cell( lat=GB_LAT, lon=GB_LON, range=6000, cid=1, **cell_key)) session.add(Cell( lat=GB_LAT, lon=GB_LON, range=9000, cid=CELLID_LAC, **cell_key)) session.flush() result = locate.search_all_sources( session, 'm', {'cell': [dict(cid=1, **cell_key)]}, client_addr=None, geoip_db=self.geoip_db) # Without a GeoIP, the mcc results in 4 different equally common # mcc values, GB not being the first one. We need to make sure # that we accept any of the country codes as a possible match # and don't discard otherwise good cell data based on this. self.assertEqual(result, {'lat': GB_LAT, 'lon': GB_LON, 'accuracy': 6000}) self.check_stats( counter=[ 'm.cell_found', 'm.cell_hit', 'm.cell_lac_found', ], )
def test_wifi_not_found_cell_fallback(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) data = [ Wifi(key="abcd", lat=30000000, lon=30000000), Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/search?key=test', {"radio": "gsm", "cell": [ dict(radio="umts", cid=4, **key), dict(radio="umts", cid=5, **key), ], "wifi": [ {"key": "abcd"}, {"key": "cdef"}, ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"status": "ok", "lat": 1.0010000, "lon": 1.0020000, "accuracy": 35000})
def test_local_export(self): session = self.db_master_session k = dict(mcc=1, mnc=2, lac=4) gsm = RADIO_TYPE['gsm'] for i in range(190, 200): session.add(Cell(radio=gsm, cid=i, lat=1.0, lon=2.0, **k)) # add one incomplete / unprocessed cell session.add(Cell(cid=210, lat=None, lon=None, **k)) session.commit() with selfdestruct_tempdir() as d: path = os.path.join(d, 'export.csv.gz') cond = and_(cell_table.c.cid != CELLID_LAC, cell_table.c.lat.isnot(None)) write_stations_to_csv(session, cell_table, CELL_COLUMNS, cond, path, make_cell_export_dict, CELL_FIELDS) with GzipFile(path, "rb") as f: r = csv.DictReader(f, CELL_FIELDS) header = r.next() self.assertTrue('area' in header.values()) self.assertEqual(header, CELL_HEADER_DICT) cid = 190 for d in r: t = dict(radio='GSM', cid=cid, **k) t = dict([(n, str(v)) for (n, v) in t.items()]) self.assertDictContainsSubset(t, d) cid += 1 self.assertEqual(r.line_num, 11) self.assertEqual(cid, 200)
def test_cell_hit_ignores_lac(self): app = self.app session = self.db_slave_session key = dict(mcc=1, mnc=2, lac=3) data = [ Cell(lat=10000000, lon=10000000, radio=2, cid=4, **key), Cell(lat=10020000, lon=10040000, radio=2, cid=5, **key), Cell(lat=10060000, lon=10060000, radio=2, cid=6, **key), Cell(lat=10026666, lon=10033333, radio=2, cid=CELLID_LAC, range=50000, **key), ] session.add_all(data) session.commit() res = app.post_json( '/v1/search?key=test', {"radio": "gsm", "cell": [ dict(radio="umts", cid=5, **key), ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"status": "ok", "lat": 1.0020000, "lon": 1.0040000, "accuracy": 35000})
def install_fixtures(self): session = self.db.session() PARIS_LAT_DEG = from_degrees(PARIS_LAT) PARIS_LON_DEG = from_degrees(PARIS_LON) qry = session.query(Cell) if qry.count() > 0: session.query(Cell).delete() lat = from_degrees(PARIS_LAT) lon = from_degrees(PARIS_LON) key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) data = [ Cell(lat=lat, lon=lon, radio=2, cid=4, **key), Cell(lat=lat + 20000, lon=lon + 40000, radio=2, cid=5, **key), ] session.add_all(data) if session.query(Wifi).count() > 0: session.query(Wifi).delete() wifis = [ Wifi(key="A1", lat=PARIS_LAT_DEG, lon=PARIS_LON_DEG), Wifi(key="B2", lat=PARIS_LAT_DEG, lon=PARIS_LON_DEG), Wifi(key="C3", lat=PARIS_LAT_DEG, lon=PARIS_LON_DEG), Wifi(key="D4", lat=None, lon=None), ] session.add_all(wifis) session.commit()
def test_cell_ignore_invalid_lac_cid(self): session = self.db_slave_session lat = PARIS_LAT lon = PARIS_LON gsm = RADIO_TYPE['gsm'] lte = RADIO_TYPE['lte'] key = dict(mcc=FRANCE_MCC, mnc=2, lac=3) ignored_key = dict(mcc=FRANCE_MCC, mnc=2, lac=-1, cid=-1) data = [ Cell(lat=lat, lon=lon, radio=gsm, cid=4, **key), Cell(lat=lat + 0.002, lon=lon + 0.004, radio=gsm, cid=5, **key), Cell(lat=lat, lon=lon, radio=gsm, **ignored_key), Cell(lat=lat + 0.002, lon=lon + 0.004, radio=lte, **ignored_key), ] session.add_all(data) session.flush() result = locate.search_all_sources( session, 'm', {"cell": [ dict(radio="gsm", cid=4, **key), dict(radio="gsm", cid=5, **key), dict(radio="gsm", cid=5, mcc=FRANCE_MCC, mnc=2, lac=-1), dict(radio="gsm", cid=-1, mcc=FRANCE_MCC, mnc=2, lac=3), ]}) self.assertEqual(result, {'lat': PARIS_LAT + 0.001, 'lon': PARIS_LON + 0.002, 'accuracy': CELL_MIN_ACCURACY})
def test_inconsistent_cell_radio_in_towers(self): app = self.app session = self.get_session() cells = [ Cell(lat=PARIS_LAT, lon=PARIS_LON, radio=RADIO_TYPE['gsm'], mcc=FRANCE_MCC, mnc=1, lac=2, cid=3, range=10000), Cell(lat=PARIS_LAT, lon=PARIS_LON, radio=RADIO_TYPE['gsm'], mcc=FRANCE_MCC, mnc=1, lac=2, cid=CELLID_LAC, range=20000), Cell(lat=PARIS_LAT + 0.002, lon=PARIS_LON + 0.004, radio=RADIO_TYPE['umts'], mcc=FRANCE_MCC, mnc=2, lac=3, cid=4, range=2000), Cell(lat=PARIS_LAT + 0.002, lon=PARIS_LON + 0.004, radio=RADIO_TYPE['umts'], mcc=FRANCE_MCC, mnc=2, lac=3, cid=CELLID_LAC, range=15000), ] session.add_all(cells) session.commit() res = app.post_json( '%s?key=test' % self.url, { "radioType": "cdma", "cellTowers": [ {"radio": "gsm", "mobileCountryCode": FRANCE_MCC, "mobileNetworkCode": 1, "locationAreaCode": 2, "cellId": 3}, {"radio": "wcdma", "mobileCountryCode": FRANCE_MCC, "mobileNetworkCode": 2, "locationAreaCode": 3, "cellId": 4}, ]}, status=200) self.check_stats( counter=[self.metric_url + '.200', self.metric + '.api_key.test'] ) self.assertEqual(res.content_type, 'application/json') location = res.json['location'] self.assertAlmostEquals(location['lat'], PARIS_LAT + 0.002) self.assertAlmostEquals(location['lng'], PARIS_LON + 0.004) self.assertEqual(res.json['accuracy'], CELL_MIN_ACCURACY)
def test_location_update_cell(self): now = util.utcnow() before = now - timedelta(days=1) schema = ValidCellKeySchema() session = self.db_master_session k1 = dict(radio=1, mcc=1, mnc=2, lac=3, cid=4) k2 = dict(radio=1, mcc=1, mnc=2, lac=6, cid=8) k3 = dict(radio=1, mcc=1, mnc=2, lac=schema.fields['lac'].missing, cid=schema.fields['cid'].missing) data = [ Cell(new_measures=3, total_measures=5, **k1), CellObservation(lat=1.0, lon=1.0, created=now, **k1), CellObservation(lat=1.002, lon=1.003, created=now, **k1), CellObservation(lat=1.004, lon=1.006, created=now, **k1), # The lac, cid are invalid and should be skipped CellObservation(lat=1.5, lon=1.5, created=now, **k3), CellObservation(lat=1.502, lon=1.503, created=now, **k3), Cell(lat=2.0, lon=2.0, new_measures=2, total_measures=4, **k2), # the lat/lon is bogus and mismatches the line above on purpose # to make sure old observations are skipped CellObservation(lat=-1.0, lon=-1.0, created=before, **k2), CellObservation(lat=-1.0, lon=-1.0, created=before, **k2), CellObservation(lat=2.002, lon=2.004, created=now, **k2), CellObservation(lat=2.002, lon=2.004, created=now, **k2), ] session.add_all(data) session.commit() result = location_update_cell.delay(min_new=1) self.assertEqual(result.get(), (2, 0)) self.check_stats( total=2, timer=['task.data.location_update_cell'], gauge=['task.data.location_update_cell.new_measures_1_100'], ) cells = session.query(Cell).all() self.assertEqual(len(cells), 2) self.assertEqual([c.new_measures for c in cells], [0, 0]) for cell in cells: if cell.cid == 4: self.assertEqual(cell.lat, 1.002) self.assertEqual(cell.lon, 1.003) elif cell.cid == 8: self.assertEqual(cell.lat, 2.001) self.assertEqual(cell.lon, 2.002)
def test_ok_cell(self): app = self.app session = self.db_slave_session cell = Cell() cell.lat = 123456781 cell.lon = 234567892 cell.radio = 0 cell.mcc = 123 cell.mnc = 1 cell.lac = 2 cell.cid = 1234 session.add(cell) session.commit() res = app.post_json( '/v1/geolocate?key=test', { "radioType": "gsm", "cellTowers": [ {"mobileCountryCode": 123, "mobileNetworkCode": 1, "locationAreaCode": 2, "cellId": 1234}, ]}, status=200) self.check_expected_heka_messages( counter=['http.request', 'geolocate.api_key.test'] ) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"location": {"lat": 12.3456781, "lng": 23.4567892}, "accuracy": 35000.0})
def test_cell_max_min_range_update(self): from ichnaea.tasks import cell_location_update session = self.db_master_session k1 = dict(radio=1, mcc=1, mnc=2, lac=3, cid=4) data = [ Cell(lat=10010000, lon=-10010000, max_lat=10020000, min_lat=10000000, max_lon=-10000000, min_lon=-10020000, new_measures=2, total_measures=4, **k1), CellMeasure(lat=10010000, lon=-10030000, **k1), CellMeasure(lat=10050000, lon=-10070000, **k1), ] session.add_all(data) session.commit() result = cell_location_update.delay(min_new=1) self.assertEqual(result.get(), (1, 0)) cells = session.query(Cell).all() self.assertEqual(len(cells), 1) cell = cells[0] self.assertEqual(cell.lat, 10020000) self.assertEqual(cell.max_lat, 10050000) self.assertEqual(cell.min_lat, 10000000) self.assertEqual(cell.lon, -10030000) self.assertEqual(cell.max_lon, -10000000) self.assertEqual(cell.min_lon, -10070000) # independent calculation: the cell bounding box is # (1.000, -1.007) to (1.005, -1.000), and distance # between those is 956.43m, int(round(dist/2.0)) is 478m self.assertEqual(cell.range, 478)
def add_line_of_cells_and_scan_lac(self): session = self.session big = 1.0 small = big / 10 keys = dict(radio=Radio.cdma, mcc=1, mnc=1, lac=1) observations = [ CellObservation(lat=ctr + xd, lon=ctr + yd, cid=cell, **keys) for cell in range(10) for ctr in [cell * big] for (xd, yd) in [(small, small), (small, -small), (-small, small), (-small, -small)] ] session.add_all(observations) cells = [ Cell(lat=ctr, lon=ctr, cid=cell, new_measures=4, total_measures=1, **keys) for cell in range(10) for ctr in [cell * big] ] session.add_all(cells) session.commit() result = location_update_cell.delay(min_new=0, max_new=9999, batch=len(observations)) self.assertEqual(result.get(), (len(cells), 0)) scan_areas.delay()
def test_cell_mcc_mnc_strings(self): # mcc and mnc are officially defined as strings, where "01" is # different from "1". In practice many systems ours included treat # them as integers, so both of these are encoded as 1 instead. # Some clients sends us these values as strings, some as integers, # so we want to make sure we support both. app = self.app session = self.db_slave_session cell = Cell( lat=PARIS_LAT, lon=PARIS_LON, range=1000, radio=RADIO_TYPE['gsm'], mcc=FRANCE_MCC, mnc=1, lac=2, cid=3) session.add(cell) session.commit() res = app.post_json( '%s?key=test' % self.url, { "radioType": "gsm", "cellTowers": [ {"mobileCountryCode": str(FRANCE_MCC), "mobileNetworkCode": "01", "locationAreaCode": 2, "cellId": 3}, ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"location": {"lat": PARIS_LAT, "lng": PARIS_LON}, "accuracy": CELL_MIN_ACCURACY})
def add_line_of_cells_and_scan_lac(self): from ichnaea.tasks import cell_location_update, scan_lacs session = self.db_master_session big = 10000000 small = big / 10 keys = dict(radio=1, mcc=1, mnc=1, lac=1) measures = [ CellMeasure(lat=ctr + xd, lon=ctr + yd, cid=cell, **keys) for cell in range(0, 10) for ctr in [cell * big] for (xd, yd) in [(small, small), (small, -small), (-small, small), (-small, -small)] ] session.add_all(measures) cells = [ Cell(lat=ctr, lon=ctr, cid=cell, new_measures=4, total_measures=1, **keys) for cell in range(0, 10) for ctr in [cell * big] ] session.add_all(cells) session.commit() result = cell_location_update.delay(min_new=0, max_new=9999, batch=len(measures)) self.assertEqual(result.get(), (len(cells), 0)) scan_lacs.delay()
def test_backfill_cell_location_update(self): from ichnaea.tasks import backfill_cell_location_update session = self.db_master_session k1 = dict(radio=1, mcc=1, mnc=2, lac=3, cid=4) data = [ Cell(lat=10010000, lon=10010000, new_measures=0, total_measures=1, **k1), CellMeasure(lat=10000000, lon=10000000, **k1), CellMeasure(lat=10050000, lon=10080000, **k1), ] session.add_all(data) session.commit() query = session.query(CellMeasure.id) cm_ids = [x[0] for x in query.all()] # TODO: refactor this to be constants in the method new_measures = [((1, 1, 2, 3, 4), cm_ids)] result = backfill_cell_location_update.delay(new_measures) self.assertEqual(result.get(), (1, 0)) cells = session.query(Cell).filter(Cell.cid != CELLID_LAC).all() self.assertEqual(len(cells), 1) cell = cells[0] self.assertEqual(cell.lat, 10020000) self.assertEqual(cell.lon, 10030000) self.assertEqual(cell.new_measures, 0) self.assertEqual(cell.total_measures, 3)
def test_unthrottle_cell_measures(self): session = self.db_master_session block = MeasureBlock() block.measure_type = MEASURE_TYPE_CODE['cell'] block.start_id = 120 block.end_id = 140 block.s3_key = 'fake_key' block.archive_sha = 'fake_sha' block.archive_date = None session.add(block) gsm = RADIO_TYPE['gsm'] k = dict(radio=gsm, mcc=1, mnc=2, lac=4, lat=1.0, lon=1.0) for i in range(100, 150): session.add(CellMeasure(id=i, cid=i, created=self.really_old, **k)) session.add(Cell(total_measures=11000, cid=i, **k)) session.commit() with patch.object(S3Backend, 'check_archive', lambda x, y, z: True): delete_cellmeasure_records.delay(batch=3).get() cell_unthrottle_measures.delay(10000, 1000).get() cells = session.query(Cell).all() self.assertEquals(len(cells), 50) for cell in cells: if 120 <= cell.cid and cell.cid < 140: self.assertEquals(cell.total_measures, 0) else: self.assertEquals(cell.total_measures, 1) self.check_stats(counter=['items.cell_unthrottled'])
def test_unknown_api_key(self): app = self.app session = self.db_slave_session key = dict(mcc=FRANCE_MCC, mnc=2, lac=3, cid=4) session.add(Cell( lat=PARIS_LAT, lon=PARIS_LON, range=1000, radio=RADIO_TYPE['gsm'], **key) ) session.commit() res = app.post_json( '%s?key=unknown_key' % self.url, { "radioType": "gsm", "cellTowers": [ {"mobileCountryCode": FRANCE_MCC, "mobileNetworkCode": 2, "locationAreaCode": 3, "cellId": 4}, ] }, status=400) self.assertEqual(res.content_type, 'application/json') self.assertEqual(u'Invalid API key', res.json['error']['message']) self.check_stats( counter=[self.metric + '.unknown_api_key'])
def test_ok_cell_radio_in_celltowers_dupes(self): # This test covered a bug related to FxOS calling the # geolocate API incorrectly. app = self.app session = self.db_slave_session cell = Cell() cell.lat = PARIS_LAT cell.lon = PARIS_LON cell.radio = 0 cell.mcc = FRANCE_MCC cell.mnc = 1 cell.lac = 2 cell.cid = 1234 cell.range = 1000 session.add(cell) session.commit() res = app.post_json( '%s?key=test' % self.url, { "cellTowers": [ {"radio": "gsm", "mobileCountryCode": FRANCE_MCC, "mobileNetworkCode": 1, "locationAreaCode": 2, "cellId": 1234}, {"radio": "gsm", "mobileCountryCode": FRANCE_MCC, "mobileNetworkCode": 1, "locationAreaCode": 2, "cellId": 1234}, ]}, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {"location": {"lat": PARIS_LAT, "lng": PARIS_LON}, "accuracy": CELL_MIN_ACCURACY})
def test_ok_cell(self): app = self.app session = self.db_slave_session cell = Cell() cell.lat = 123456781 cell.lon = 234567892 cell.radio = 0 cell.mcc = 123 cell.mnc = 1 cell.lac = 2 cell.cid = 1234 session.add(cell) session.commit() res = app.post_json('/v1/geolocate', { "radioType": "gsm", "cellTowers": [ { "mobileCountryCode": 123, "mobileNetworkCode": 1, "locationAreaCode": 2, "cellId": 1234 }, ] }, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual( res.body, '{"location": {"lat": 12.3456781, ' '"lng": 23.4567892}, "accuracy": 35000.0}')
def test_geoip_mcc_multiple_unknown_mismatching_cell(self): session = self.db_slave_session gsm = RADIO_TYPE['gsm'] cell_key = {'radio': gsm, 'mnc': 1, 'lac': 1, 'cid': 1} cells = [ dict(mcc=GB_MCC, **cell_key), dict(mcc=USA_MCC, **cell_key), ] # Only add the matching cell to the DB session.add(Cell(**cells[0])) session.flush() result = locate.search_all_sources( session, 'm', {'cell': cells}, client_addr=GB_IP, geoip_db=self.geoip_db) self.assertEqual(result, {'lat': GB_LAT, 'lon': GB_LON, 'accuracy': GB_RADIUS}) self.check_stats( counter=[ 'm.anomaly.multiple_mccs', 'm.country_from_geoip', ], )