def test_inconsistent_cell_radio_type_in_towers(self): cell = CellFactory(radio=Radio.umts, range=15000) cell2 = CellFactory(radio=Radio.gsm, range=35000, lat=cell.lat + 0.0002, lon=cell.lon) self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "radioType": Radio.cdma.name, "cellTowers": [ { "radio": "cdma", "radioType": "wcdma", "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, { "radioType": cell2.radio.name, "mobileCountryCode": cell2.mcc, "mobileNetworkCode": cell2.mnc, "locationAreaCode": cell2.lac, "cellId": cell2.cid }, ] }, status=200) location = res.json['location'] self.assertAlmostEquals(location['lat'], cell.lat) self.assertAlmostEquals(location['lng'], cell.lon) self.assertEqual(res.json['accuracy'], cell.range)
def test_ok_partial_cell(self): session = self.session cell = CellFactory() session.flush() res = self.app.post_json('%s?key=test' % self.url, { "cellTowers": [{ "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid, "psc": cell.psc }, { "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "psc": cell.psc + 1, }] }, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, { "location": { "lat": cell.lat, "lng": cell.lon }, "accuracy": cell.range })
def test_ok_cell_radio_in_celltowers_dupes(self): # This test covers a bug related to FxOS calling the # geolocate API incorrectly. cell = CellFactory() self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "cellTowers": [ { "radio": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, { "radio": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, status=200) self.assertEqual(res.json, { "location": { "lat": cell.lat, "lng": cell.lon }, "accuracy": cell.range })
def test_ok_cell_radiotype_in_celltowers(self): # This test covers an extension to the geolocate API cell = CellFactory() self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "cellTowers": [ { "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, status=200) self.assertEqual(res.json, { "location": { "lat": cell.lat, "lng": cell.lon }, "accuracy": cell.range })
def test_lte_radio(self): cell = CellFactory(radio=Radio.lte) self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "cellTowers": [ { "radio": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, 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'], cell.lat) self.assertAlmostEquals(location['lng'], cell.lon) self.assertEqual(res.json['accuracy'], cell.range)
def test_ok_cell(self): cell = CellFactory() self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "radioType": cell.radio.name, "cellTowers": [ { "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, status=200) self.check_stats(counter=[ self.metric_url + '.200', self.metric + '.api_key.test', self.metric + '.api_log.test.cell_hit' ]) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, { "location": { "lat": cell.lat, "lng": cell.lon }, "accuracy": cell.range })
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. cell = CellFactory(mnc=1) self.session.flush() res = self.app.post_json('%s?key=test' % self.url, { "cellTowers": [ { "radioType": cell.radio.name, "mobileCountryCode": str(cell.mcc), "mobileNetworkCode": "01", "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, status=200) self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, { "location": { "lat": cell.lat, "lng": cell.lon }, "accuracy": cell.range })
def test_unique_cell_histogram(self): session = self.session today = util.utcnow() yesterday = (today - timedelta(1)) two_days = (today - timedelta(2)) long_ago = (today - timedelta(3)) CellFactory(created=long_ago, radio=Radio.gsm) CellFactory(created=two_days, radio=Radio.umts) CellFactory(created=two_days, radio=Radio.umts, cid=50) CellFactory(created=yesterday, radio=Radio.lte, cid=50) CellFactory(created=today, radio=Radio.gsm, mnc=30) session.flush() result = unique_cell_histogram.delay(ago=3) self.assertEqual(result.get(), 1) stats = session.query(Stat).order_by(Stat.time).all() self.assertEqual(len(stats), 1) self.assertEqual(stats[0].key, StatKey.unique_cell) self.assertEqual(stats[0].time, long_ago.date()) self.assertEqual(stats[0].value, 1) # fill up newer dates unique_cell_histogram.delay(ago=2).get() unique_cell_histogram.delay(ago=1).get() unique_cell_histogram.delay(ago=0).get() # test duplicate execution unique_cell_histogram.delay(ago=1).get() stats = session.query(Stat.time, Stat.value).order_by(Stat.time).all() self.assertEqual(len(stats), 4) self.assertEqual(dict(stats), { long_ago.date(): 1, two_days.date(): 3, yesterday.date(): 4, today.date(): 5})
def test_no_api_key(self): cell = CellFactory() self.session.flush() res = self.app.post_json(self.url, { "cellTowers": [ { "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid }, ] }, 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 + '.no_api_key'])
def test_ok_partial_cell(self): session = self.session cell = CellFactory() session.flush() res = self.app.post_json('/v1/geosubmit?key=test', { "items": [ { "latitude": cell.lat, "longitude": cell.lon, "cellTowers": [{ "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid, "psc": cell.psc }, { "radioType": cell.radio.name, "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "psc": cell.psc + 1, }] }, ] }, status=200) # check that we get an empty response self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {}) observations = session.query(CellObservation).all() self.assertEqual(len(observations), 2) pscs = set([obs.psc for obs in observations]) self.assertEqual(pscs, set([cell.psc, cell.psc + 1]))
def test_location_update_cell(self): now = util.utcnow() before = now - timedelta(hours=1) schema = ValidCellKeySchema() obs_factory = CellObservationFactory invalid_key = dict(lac=schema.fields['lac'].missing, cid=schema.fields['cid'].missing) cell1 = CellFactory(new_measures=3, total_measures=5) lat1, lon1 = (cell1.lat, cell1.lon) key1 = dict(lac=cell1.lac, cid=cell1.cid) obs_factory(lat=lat1, lon=lon1, created=now, **key1) obs_factory(lat=lat1 + 0.004, lon=lon1 + 0.006, created=now, **key1) obs_factory(lat=lat1 + 0.006, lon=lon1 + 0.009, created=now, **key1) # The lac, cid are invalid and should be skipped obs_factory.create_batch(2, created=now, **invalid_key) cell2 = CellFactory(lat=lat1 + 1.0, lon=lon1 + 1.0, new_measures=2, total_measures=4) lat2, lon2 = (cell2.lat, cell2.lon) key2 = dict(lac=cell2.lac, cid=cell2.cid) # the lat/lon is bogus and mismatches the line above on purpose # to make sure old observations are skipped obs_factory(lat=lat2 - 2.0, lon=lon2 - 2.0, created=before, **key2) obs_factory(lat=lat2 - 2.0, lon=lon2 - 2.0, created=before, **key2) obs_factory(lat=lat2 + 0.001, lon=lon2 + 0.002, created=now, **key2) obs_factory(lat=lat2 + 0.003, lon=lon2 + 0.006, created=now, **key2) cell3 = CellFactory(new_measures=10, total_measures=100000) lat3, lon3 = (cell3.lat, cell3.lon) obs_factory.create_batch(10, lat=lat3 + 1.0, lon=lon3 + 1.0, **dict(lac=cell3.lac, cid=cell3.cid)) self.session.commit() result = location_update_cell.delay(min_new=1) self.assertEqual(result.get(), (3, 0)) self.check_stats( total=2, timer=['task.data.location_update_cell'], gauge=['task.data.location_update_cell.new_measures_1_100'], ) cells = self.session.query(Cell).all() self.assertEqual(len(cells), 3) self.assertEqual(set([c.new_measures for c in cells]), set([0])) for cell in cells: if cell.hashkey() == cell1.hashkey(): self.assertEqual(cell.lat, lat1 + 0.002) self.assertEqual(cell.lon, lon1 + 0.003) if cell.hashkey() == cell2.hashkey(): self.assertEqual(cell.lat, lat2 + 0.001) self.assertEqual(cell.lon, lon2 + 0.002) if cell.hashkey() == cell3.hashkey(): expected_lat = ((lat3 * 1000) + (lat3 + 1.0) * 10) / 1010 expected_lon = ((lon3 * 1000) + (lon3 + 1.0) * 10) / 1010 self.assertAlmostEqual(cell.lat, expected_lat, 7) self.assertAlmostEqual(cell.lon, expected_lon, 7)
def test_ok_cell(self): session = self.session cell = CellFactory() new_cell = CellFactory.build() session.flush() res = self.app.post_json('/v1/geosubmit?key=test', { "items": [ { "latitude": cell.lat, "longitude": cell.lon, "radioType": cell.radio.name, "cellTowers": [{ "mobileCountryCode": cell.mcc, "mobileNetworkCode": cell.mnc, "locationAreaCode": cell.lac, "cellId": cell.cid, }] }, { "latitude": new_cell.lat, "longitude": new_cell.lon, "cellTowers": [{ "radioType": new_cell.radio.name, "mobileCountryCode": new_cell.mcc, "mobileNetworkCode": new_cell.mnc, "locationAreaCode": new_cell.lac, "cellId": new_cell.cid, }] }, ] }, status=200) # check that we get an empty response self.assertEqual(res.content_type, 'application/json') self.assertEqual(res.json, {}) self.assertEqual(session.query(Cell).count(), 2) observations = session.query(CellObservation).all() self.assertEqual(len(observations), 2) radios = set([obs.radio for obs in observations]) self.assertEqual(radios, set([cell.radio, new_cell.radio])) self.check_stats(counter=[ 'geosubmit.api_key.test', 'items.api_log.test.uploaded.batches', 'items.api_log.test.uploaded.reports', 'items.api_log.test.uploaded.cell_observations', 'items.uploaded.cell_observations', 'items.uploaded.batches', 'items.uploaded.reports', 'request.v1.geosubmit.200', ], timer=[ 'items.api_log.test.uploaded.batch_size', 'items.uploaded.batch_size', 'request.v1.geosubmit' ])