def test_export_full(self, celery, session): now = util.utcnow() long_ago = now - timedelta(days=367) CellShardFactory.create_batch(10, radio=Radio.gsm) CellShardFactory( radio=Radio.gsm, created=long_ago, modified=long_ago, last_seen=long_ago.date(), ) session.commit() pattern = re.compile( r"MLS-full-cell-export-\d+-\d+-\d+T000000\.csv\.gz") mock_conn = mock.MagicMock() mock_bucket = mock.MagicMock(name="bucket") mock_obj = mock.MagicMock() mock_conn.return_value.Bucket.return_value = mock_bucket mock_bucket.Object.return_value = mock_obj with mock.patch.object(boto3, "resource", mock_conn): cell_export_full(_bucket="bucket") s3_key = mock_bucket.Object.call_args[0][0] assert pattern.search(s3_key) tmp_file = mock_obj.upload_file.call_args[0][0] assert pattern.search(tmp_file)
def test_export_full(self, celery, session): now = util.utcnow() long_ago = now - timedelta(days=367) CellShardFactory.create_batch(10, radio=Radio.gsm) CellShardFactory( radio=Radio.gsm, created=long_ago, modified=long_ago, last_seen=long_ago.date()) session.commit() pattern = re.compile( r'MLS-full-cell-export-\d+-\d+-\d+T000000\.csv\.gz') mock_conn = mock.MagicMock() mock_bucket = mock.MagicMock(name='bucket') mock_obj = mock.MagicMock() mock_conn.return_value.Bucket.return_value = mock_bucket mock_bucket.Object.return_value = mock_obj with mock.patch.object(boto3, 'resource', mock_conn): cell_export_full(_bucket='bucket') s3_key = mock_bucket.Object.call_args[0][0] assert pattern.search(s3_key) tmp_file = mock_obj.upload_file.call_args[0][0] assert pattern.search(tmp_file)
def test_export_full(self): CellShardFactory.create_batch(10, radio=Radio.gsm) self.session.commit() with mock_s3() as mock_key: cell_export_full(_bucket='localhost.bucket') pat = r'MLS-full-cell-export-\d+-\d+-\d+T000000\.csv\.gz' self.assertRegex(mock_key.key, pat) method = mock_key.set_contents_from_filename self.assertRegex(method.call_args[0][0], pat)
def test_export_full(self): CellShardFactory.create_batch(10, radio=Radio.gsm) self.session.commit() with mock_s3() as mock_key: cell_export_full(_bucket='localhost.bucket') pat = r'MLS-full-cell-export-\d+-\d+-\d+T000000\.csv\.gz' self.assertRegex(mock_key.key, pat) method = mock_key.set_contents_from_filename self.assertRegex(method.call_args[0][0], pat)
def test_export_diff(self, celery, session): CellShardFactory.create_batch(10, radio=Radio.gsm) session.commit() pattern = re.compile( r'MLS-diff-cell-export-\d+-\d+-\d+T\d+0000\.csv\.gz') with mock_s3() as mock_key: cell_export_diff(_bucket='localhost.bucket') assert pattern.search(mock_key.key) method = mock_key.set_contents_from_filename assert pattern.search(method.call_args[0][0])
def test_export_full(self, celery, session): now = util.utcnow() long_ago = now - timedelta(days=367) CellShardFactory.create_batch(10, radio=Radio.gsm) CellShardFactory( radio=Radio.gsm, created=long_ago, modified=long_ago, last_seen=long_ago.date()) session.commit() pattern = re.compile( r'MLS-full-cell-export-\d+-\d+-\d+T000000\.csv\.gz') with mock_s3() as mock_key: cell_export_full(_bucket='localhost.bucket') assert pattern.search(mock_key.key) method = mock_key.set_contents_from_filename assert pattern.search(method.call_args[0][0])
def test_export_diff(self, celery, session): CellShardFactory.create_batch(10, radio=Radio.gsm) session.commit() pattern = re.compile(r"MLS-diff-cell-export-\d+-\d+-\d+T\d+0000\.csv\.gz") mock_conn = mock.MagicMock() mock_bucket = mock.MagicMock(name="bucket") mock_obj = mock.MagicMock() mock_conn.return_value.Bucket.return_value = mock_bucket mock_bucket.Object.return_value = mock_obj with mock.patch.object(boto3, "resource", mock_conn): cell_export_diff(_bucket="bucket") s3_key = mock_bucket.Object.call_args[0][0] assert pattern.search(s3_key) tmp_file = mock_obj.upload_file.call_args[0][0] assert pattern.search(tmp_file)
def test_export_diff(self, celery, session): CellShardFactory.create_batch(10, radio=Radio.gsm) session.commit() pattern = re.compile( r'MLS-diff-cell-export-\d+-\d+-\d+T\d+0000\.csv\.gz') mock_conn = mock.MagicMock() mock_bucket = mock.MagicMock(name='bucket') mock_obj = mock.MagicMock() mock_conn.return_value.Bucket.return_value = mock_bucket mock_bucket.Object.return_value = mock_obj with mock.patch.object(boto3, 'resource', mock_conn): cell_export_diff(_bucket='bucket') s3_key = mock_bucket.Object.call_args[0][0] assert pattern.search(s3_key) tmp_file = mock_obj.upload_file.call_args[0][0] assert pattern.search(tmp_file)
def test_fallback(self): # this tests a cell + wifi based query which gets a cell based # internal result and continues on to the fallback to get a # better wifi based result cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = self.session.query(ApiKey).get('test') api_key.allow_fallback = True self.session.flush() with requests_mock.Mocker() as mock: response_result = { 'location': { 'lat': 1.0, 'lng': 1.0, }, 'accuracy': 100, } mock.register_uri('POST', requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(body=query) send_json = mock.request_history[0].json() self.assertEqual(len(send_json['cellTowers']), 2) self.assertEqual(len(send_json['wifiAccessPoints']), 3) self.assertEqual(send_json['cellTowers'][0]['radioType'], 'wcdma') self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) self.check_stats(counter=[ ('request', [self.metric_path, 'method:post', 'status:200']), (self.metric_type + '.request', [self.metric_path, 'key:test']), (self.metric_type + '.query', [ 'key:test', 'region:none', 'geoip:false', 'cell:many', 'wifi:many' ]), (self.metric_type + '.result', [ 'key:test', 'region:none', 'fallback_allowed:true', 'accuracy:high', 'status:hit', 'source:fallback' ]), (self.metric_type + '.source', [ 'key:test', 'region:none', 'source:internal', 'accuracy:high', 'status:miss' ]), (self.metric_type + '.source', [ 'key:test', 'region:none', 'source:fallback', 'accuracy:high', 'status:hit' ]), ], timer=[ ('request', [self.metric_path, 'method:post']), ])
def test_fallback_used_with_geoip(self, app, session, metricsmock): cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) ApiKeyFactory(valid_key="fall", allow_fallback=True) session.flush() with requests_mock.Mocker() as mock: response_result = {"location": {"lat": 1.0, "lng": 1.0}, "accuracy": 100.0} mock.register_uri("POST", requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(app, api_key="fall", body=query, ip=self.test_ip) send_json = mock.request_history[0].json() assert len(send_json["cellTowers"]) == 2 assert len(send_json["wifiAccessPoints"]) == 3 self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) assert metricsmock.has_record( "incr", "request", value=1, tags=[self.metric_path, "method:post", "status:200"], ) assert metricsmock.has_record( "incr", self.metric_type + ".request", value=1, tags=[self.metric_path, "key:fall"], ) assert metricsmock.has_record( "incr", self.metric_type + ".result", value=1, tags=[ "key:fall", "fallback_allowed:true", "accuracy:high", "status:hit", "source:fallback", ], ) assert metricsmock.has_record( "incr", self.metric_type + ".source", value=1, tags=["key:fall", "source:fallback", "accuracy:high", "status:hit"], ) assert metricsmock.has_record( "timing", "request.timing", tags=[self.metric_path, "method:post"] )
def test_fallback(self): # this tests a cell + wifi based query which gets a cell based # internal result and continues on to the fallback to get a # better wifi based result cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = self.session.query(ApiKey).get("test") api_key.allow_fallback = True self.session.flush() with requests_mock.Mocker() as mock: response_result = {"location": {"lat": 1.0, "lng": 1.0}, "accuracy": 100} mock.register_uri("POST", requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(body=query) send_json = mock.request_history[0].json() self.assertEqual(len(send_json["cellTowers"]), 2) self.assertEqual(len(send_json["wifiAccessPoints"]), 3) self.assertEqual(send_json["cellTowers"][0]["radioType"], "wcdma") self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) self.check_stats( counter=[ ("request", [self.metric_path, "method:post", "status:200"]), (self.metric_type + ".request", [self.metric_path, "key:test"]), (self.metric_type + ".query", ["key:test", "region:none", "geoip:false", "cell:many", "wifi:many"]), ( self.metric_type + ".result", [ "key:test", "region:none", "fallback_allowed:true", "accuracy:high", "status:hit", "source:fallback", ], ), ( self.metric_type + ".source", ["key:test", "region:none", "source:internal", "accuracy:high", "status:miss"], ), ( self.metric_type + ".source", ["key:test", "region:none", "source:fallback", "accuracy:high", "status:hit"], ), ], timer=[("request", [self.metric_path, "method:post"])], )
def test_fallback(self, app, ro_session, stats): # this tests a cell + wifi based query which gets a cell based # internal result and continues on to the fallback to get a # better wifi based result cells = CellShardFactory.create_batch( 2, session=ro_session, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = ApiKey.get(ro_session, 'test') api_key.allow_fallback = True ro_session.flush() with requests_mock.Mocker() as mock: response_result = { 'location': { 'lat': 1.0, 'lng': 1.0, }, 'accuracy': 100, } mock.register_uri( 'POST', requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(app, body=query) send_json = mock.request_history[0].json() assert len(send_json['cellTowers']) == 2 assert len(send_json['wifiAccessPoints']) == 3 assert send_json['cellTowers'][0]['radioType'] == 'wcdma' self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) stats.check(counter=[ ('request', [self.metric_path, 'method:post', 'status:200']), (self.metric_type + '.request', [self.metric_path, 'key:test']), (self.metric_type + '.query', ['key:test', 'region:none', 'geoip:false', 'blue:none', 'cell:many', 'wifi:many']), (self.metric_type + '.result', ['key:test', 'region:none', 'fallback_allowed:true', 'accuracy:high', 'status:hit', 'source:fallback']), (self.metric_type + '.source', ['key:test', 'region:none', 'source:internal', 'accuracy:high', 'status:miss']), (self.metric_type + '.source', ['key:test', 'region:none', 'source:fallback', 'accuracy:high', 'status:hit']), ], timer=[ ('request', [self.metric_path, 'method:post']), ])
def test_fallback_used_with_geoip(self): cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = self.session.query(ApiKey).get("test") api_key.allow_fallback = True self.session.flush() with requests_mock.Mocker() as mock: response_result = {"location": {"lat": 1.0, "lng": 1.0}, "accuracy": 100.0} mock.register_uri("POST", requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(body=query, ip=self.test_ip) send_json = mock.request_history[0].json() self.assertEqual(len(send_json["cellTowers"]), 2) self.assertEqual(len(send_json["wifiAccessPoints"]), 3) self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) self.check_stats( counter=[ ("request", [self.metric_path, "method:post", "status:200"]), (self.metric_type + ".request", [self.metric_path, "key:test"]), ( self.metric_type + ".result", [ "key:test", "region:GB", "fallback_allowed:true", "accuracy:high", "status:hit", "source:fallback", ], ), ( self.metric_type + ".source", ["key:test", "region:GB", "source:fallback", "accuracy:high", "status:hit"], ), ], timer=[("request", [self.metric_path, "method:post"])], )
def test_fallback_used_with_geoip(self): cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = self.session.query(ApiKey).get('test') api_key.allow_fallback = True self.session.flush() with requests_mock.Mocker() as mock: response_result = { 'location': { 'lat': 1.0, 'lng': 1.0, }, 'accuracy': 100.0, } mock.register_uri('POST', requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(body=query, ip=self.test_ip) send_json = mock.request_history[0].json() self.assertEqual(len(send_json['cellTowers']), 2) self.assertEqual(len(send_json['wifiAccessPoints']), 3) self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) self.check_stats(counter=[ ('request', [self.metric_path, 'method:post', 'status:200']), (self.metric_type + '.request', [self.metric_path, 'key:test']), (self.metric_type + '.result', [ 'key:test', 'region:GB', 'fallback_allowed:true', 'accuracy:high', 'status:hit', 'source:fallback' ]), (self.metric_type + '.source', [ 'key:test', 'region:GB', 'source:fallback', 'accuracy:high', 'status:hit' ]), ], timer=[ ('request', [self.metric_path, 'method:post']), ])
def test_fallback_used_with_geoip(self, app, ro_session, stats): cells = CellShardFactory.create_batch( 2, session=ro_session, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) api_key = ApiKey.get(ro_session, 'test') api_key.allow_fallback = True ro_session.flush() with requests_mock.Mocker() as mock: response_result = { 'location': { 'lat': 1.0, 'lng': 1.0, }, 'accuracy': 100.0, } mock.register_uri( 'POST', requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(app, body=query, ip=self.test_ip) send_json = mock.request_history[0].json() assert len(send_json['cellTowers']) == 2 assert len(send_json['wifiAccessPoints']) == 3 self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) stats.check(counter=[ ('request', [self.metric_path, 'method:post', 'status:200']), (self.metric_type + '.request', [self.metric_path, 'key:test']), (self.metric_type + '.result', ['key:test', 'region:GB', 'fallback_allowed:true', 'accuracy:high', 'status:hit', 'source:fallback']), (self.metric_type + '.source', ['key:test', 'region:GB', 'source:fallback', 'accuracy:high', 'status:hit']), ], timer=[ ('request', [self.metric_path, 'method:post']), ])
def test_blocklist_moving_cells(self): now = util.utcnow() today = now.date() obs = [] obs_factory = CellObservationFactory moving = set() cells = CellShardFactory.create_batch(4) cells.append(CellShardFactory.build()) # a cell with an entry but no prior position cell = cells[0] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 0 obs.extend([ obs_factory(lat=cell.lat + 0.01, lon=cell.lon + 0.01, **cell_key), obs_factory(lat=cell.lat + 0.02, lon=cell.lon + 0.05, **cell_key), obs_factory(lat=cell.lat + 0.03, lon=cell.lon + 0.09, **cell_key), ]) cell.lat = None cell.lon = None # a cell with a prior known position cell = cells[1] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 cell.lat += 0.1 obs.extend([ obs_factory(lat=cell.lat + 1.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # a cell with a very different prior position cell = cells[2] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 obs.extend([ obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat - 0.1, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # another cell with a prior known position (and negative lon) cell = cells[3] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 cell.lon *= -1.0 obs.extend([ obs_factory(lat=cell.lat + 1.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 2.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # an already blocklisted cell cell = cells[4] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) CellShardFactory(block_first=today, block_last=today, block_count=1, **cell_key) obs.extend([ obs_factory(lat=cell.lat, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) self.session.commit() self._queue_and_update(obs) shards = set() for cellid in moving: shards.add(CellShard.shard_model(cellid)) blocks = [] for shard in shards: for row in self.session.query(shard).all(): if row.blocked(): blocks.append(row) self.assertEqual(set([b.cellid for b in blocks]), moving)
def test_blocklist_moving_cells(self): now = util.utcnow() today = now.date() obs = [] obs_factory = CellObservationFactory moving = set() cells = CellShardFactory.create_batch(4) cells.append(CellShardFactory.build()) # a cell with an entry but no prior position cell = cells[0] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = None cell.weight = None obs.extend([ obs_factory(lat=cell.lat + 0.01, lon=cell.lon + 0.01, **cell_key), obs_factory(lat=cell.lat + 0.02, lon=cell.lon + 0.05, **cell_key), obs_factory(lat=cell.lat + 0.03, lon=cell.lon + 0.09, **cell_key), ]) cell.lat = None cell.lon = None # a cell with a prior known position cell = cells[1] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 cell.weight = 1.0 cell.lat += 0.1 obs.extend([ obs_factory(lat=cell.lat + 1.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # a cell with a very different prior position cell = cells[2] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 cell.weight = 1.0 obs.extend([ obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat - 0.1, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # another cell with a prior known position (and negative lon) cell = cells[3] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) cell.samples = 1 cell.weight = 1.0 cell.lon *= -1.0 obs.extend([ obs_factory(lat=cell.lat + 1.0, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 2.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) # an already blocklisted cell cell = cells[4] cell_key = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc, lac=cell.lac, cid=cell.cid) CellShardFactory(block_first=today, block_last=today, block_count=1, **cell_key) obs.extend([ obs_factory(lat=cell.lat, lon=cell.lon, **cell_key), obs_factory(lat=cell.lat + 3.0, lon=cell.lon, **cell_key), ]) moving.add(cell.cellid) self.session.commit() self._queue_and_update_cell(obs) shards = set() for cellid in moving: shards.add(CellShard.shard_model(cellid)) blocks = [] for shard in shards: for row in self.session.query(shard).all(): if row.blocked(): blocks.append(row) self.assertEqual(set([b.cellid for b in blocks]), moving)
def test_cell(self, sync_session): cells = CellShardFactory.create_batch(2) # Add one far away network, with no area restriction. cells.append(CellShardFactory(lat=46.5743, lon=6.3532, region="FR")) sync_session.flush() self._export(sync_session, "cell", self._cell_keys(cells))
def test_fallback(self, app, session, metricsmock, with_ip, logs): """ An external location provider can be used to improve results. A cell + wifi based query which gets a cell based internal result and continues on to the fallback to get a better wifi based result. The fallback may or may not include IP-based lookup data. """ cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) ApiKeyFactory(valid_key="fall", allow_fallback=True) session.flush() with requests_mock.Mocker() as mock: response_result = {"location": {"lat": 1.0, "lng": 1.0}, "accuracy": 100} mock.register_uri("POST", requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) if with_ip: ip = self.test_ip else: ip = None res = self._call(app, api_key="fall", body=query, ip=ip) send_json = mock.request_history[0].json() assert len(send_json["cellTowers"]) == 2 assert len(send_json["wifiAccessPoints"]) == 3 assert send_json["cellTowers"][0]["radioType"] == "wcdma" self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) metricsmock.assert_incr_once( "request", tags=[self.metric_path, "method:post", "status:200"] ) metricsmock.assert_incr_once( self.metric_type + ".request", tags=[self.metric_path, "key:fall"] ) if with_ip: metricsmock.assert_incr_once( self.metric_type + ".query", tags=["key:fall", "blue:none", "cell:many", "wifi:many"], ) else: metricsmock.assert_incr_once( self.metric_type + ".query", tags=["key:fall", "geoip:false", "blue:none", "cell:many", "wifi:many"], ) metricsmock.assert_incr_once( self.metric_type + ".result", tags=[ "key:fall", "fallback_allowed:true", "accuracy:high", "status:hit", "source:fallback", ], ) metricsmock.assert_incr_once( self.metric_type + ".source", tags=["key:fall", "source:internal", "accuracy:high", "status:miss"], ) metricsmock.assert_incr_once( self.metric_type + ".source", tags=["key:fall", "source:fallback", "accuracy:high", "status:hit"], ) log = logs.only_entry assert log["cell_valid"] == 2 assert log["wifi_valid"] == 3 assert log["fallback_allowed"] assert log["source_fallback_accuracy"] == "high" assert log["source_fallback_accuracy_min"] == "high" assert log["source_fallback_status"] == "hit"
def test_fallback(self, app, session, metricsmock): # this tests a cell + wifi based query which gets a cell based # internal result and continues on to the fallback to get a # better wifi based result cells = CellShardFactory.create_batch(2, radio=Radio.wcdma) wifis = WifiShardFactory.build_batch(3) ApiKeyFactory(valid_key="fall", allow_fallback=True) session.flush() with requests_mock.Mocker() as mock: response_result = { "location": { "lat": 1.0, "lng": 1.0 }, "accuracy": 100 } mock.register_uri("POST", requests_mock.ANY, json=response_result) query = self.model_query(cells=cells, wifis=wifis) res = self._call(app, api_key="fall", body=query) send_json = mock.request_history[0].json() assert len(send_json["cellTowers"]) == 2 assert len(send_json["wifiAccessPoints"]) == 3 assert send_json["cellTowers"][0]["radioType"] == "wcdma" self.check_model_response(res, None, lat=1.0, lon=1.0, accuracy=100) assert metricsmock.has_record( "incr", "request", value=1, tags=[self.metric_path, "method:post", "status:200"], ) assert metricsmock.has_record( "incr", self.metric_type + ".request", value=1, tags=[self.metric_path, "key:fall"], ) assert metricsmock.has_record( "incr", self.metric_type + ".query", value=1, tags=[ "key:fall", "region:none", "geoip:false", "blue:none", "cell:many", "wifi:many", ], ) assert metricsmock.has_record( "incr", self.metric_type + ".result", value=1, tags=[ "key:fall", "region:none", "fallback_allowed:true", "accuracy:high", "status:hit", "source:fallback", ], ) assert metricsmock.has_record( "incr", self.metric_type + ".source", value=1, tags=[ "key:fall", "region:none", "source:internal", "accuracy:high", "status:miss", ], ) assert metricsmock.has_record( "incr", self.metric_type + ".source", value=1, tags=[ "key:fall", "region:none", "source:fallback", "accuracy:high", "status:hit", ], ) assert metricsmock.has_record("timing", "request.timing", tags=[self.metric_path, "method:post"])