Example #1
0
    def add_reports(self, num=1, blue_factor=0, cell_factor=1, wifi_factor=2,
                    api_key='test', nickname=None,
                    blue_key=None, cell_mcc=None, wifi_key=None,
                    lat=None, lon=None):
        reports = []
        for i in range(num):
            pos = CellShardFactory.build()
            report = {
                'timestamp': time.time() * 1000.0,
                'position': {},
                'bluetoothBeacons': [],
                'cellTowers': [],
                'wifiAccessPoints': [],
            }
            report['position']['latitude'] = lat or pos.lat
            report['position']['longitude'] = lon or pos.lon
            report['position']['accuracy'] = 17.0 + i

            blues = BlueShardFactory.build_batch(blue_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for blue in blues:
                blue_data = {
                    'macAddress': blue_key or blue.mac,
                    'signalStrength': -100 + i,
                }
                report['bluetoothBeacons'].append(blue_data)

            cells = CellShardFactory.build_batch(cell_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for cell in cells:
                cell_data = {
                    'radioType': cell.radio.name,
                    'mobileCountryCode': cell_mcc or cell.mcc,
                    'mobileNetworkCode': cell.mnc,
                    'locationAreaCode': cell.lac,
                    'cellId': cell.cid,
                    'primaryScramblingCode': cell.psc,
                    'signalStrength': -110 + i,
                }
                report['cellTowers'].append(cell_data)

            wifis = WifiShardFactory.build_batch(wifi_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for wifi in wifis:
                wifi_data = {
                    'macAddress': wifi_key or wifi.mac,
                    'signalStrength': -90 + i,
                    'ssid': 'my-wifi',
                }
                report['wifiAccessPoints'].append(wifi_data)

            reports.append(report)

        items = [{'api_key': api_key,
                  'nickname': nickname,
                  'report': rep} for rep in reports]

        self.incoming_queue.enqueue(items)
        update_incoming.delay().get()
        return reports
Example #2
0
    def test_database_error(self, app, data_queues,
                            raven, session, stats, restore_db):
        cells = [
            CellShardFactory.build(radio=Radio.gsm),
            CellShardFactory.build(radio=Radio.wcdma),
            CellShardFactory.build(radio=Radio.lte),
        ]
        wifis = WifiShardFactory.build_batch(2)

        for model in (CellArea, ):
            session.execute(text('drop table %s;' % model.__tablename__))
        for name in set([cell.__tablename__ for cell in cells]):
            session.execute(text('drop table %s;' % name))
        for name in set([wifi.__tablename__ for wifi in wifis]):
            session.execute(text('drop table %s;' % name))

        query = self.model_query(cells=cells, wifis=wifis)
        res = self._call(app, body=query, ip=self.test_ip)
        self.check_response(data_queues, res, 'ok', fallback='ipf')
        self.check_queue(data_queues, 0)
        stats.check(counter=[
            ('request', [self.metric_path, 'method:post', 'status:200']),
        ], timer=[
            ('request', [self.metric_path, 'method:post']),
        ])
        if self.apikey_metrics:
            stats.check(counter=[
                (self.metric_type + '.result',
                    ['key:test', 'region:GB', 'fallback_allowed:false',
                     'accuracy:high', 'status:miss']),
            ])

        raven.check([('ProgrammingError', 3)])
Example #3
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")

        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)
Example #4
0
    def test_database_error(self, db_errors=0):
        cells = [
            CellShardFactory.build(radio=Radio.gsm),
            CellShardFactory.build(radio=Radio.wcdma),
            CellShardFactory.build(radio=Radio.lte),
        ]
        wifis = WifiShardFactory.build_batch(2)

        for model in (CellArea, CellOCID, CellAreaOCID):
            self.session.execute(text("drop table %s;" % model.__tablename__))
        for name in set([cell.__tablename__ for cell in cells]):
            self.session.execute(text("drop table %s;" % name))
        for name in set([wifi.__tablename__ for wifi in wifis]):
            self.session.execute(text("drop table %s;" % name))

        query = self.model_query(cells=cells, wifis=wifis)
        res = self._call(body=query, ip=self.test_ip)
        self.check_response(res, "ok")
        self.check_stats(
            counter=[("request", [self.metric_path, "method:post", "status:200"])],
            timer=[("request", [self.metric_path, "method:post"])],
        )
        if self.apikey_metrics:
            self.check_stats(
                counter=[
                    (
                        self.metric_type + ".result",
                        ["key:test", "region:GB", "fallback_allowed:false", "accuracy:high", "status:miss"],
                    )
                ]
            )

        self.check_raven([("ProgrammingError", db_errors)])
Example #5
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')

        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)
Example #6
0
    def test_max_min_radius_update(self):
        cell = CellShardFactory(radius=150, samples=3, weight=3.0)
        cell_lat = cell.lat
        cell_lon = cell.lon
        cell.max_lat = cell.lat + 0.001
        cell.min_lat = cell.lat - 0.001
        cell.max_lon = cell.lon + 0.001
        cell.min_lon = cell.lon - 0.001
        k1 = dict(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc,
                  lac=cell.lac, cid=cell.cid)

        obs_factory = CellObservationFactory
        obs = [
            obs_factory(lat=cell.lat, lon=cell.lon - 0.002, **k1),
            obs_factory(lat=cell.lat + 0.004, lon=cell.lon - 0.006, **k1),
        ]

        self.session.commit()
        self._queue_and_update_cell(obs)

        shard = CellShard.shard_model(cell.cellid)
        cells = self.session.query(shard).all()
        self.assertEqual(len(cells), 1)
        cell = cells[0]
        self.assertAlmostEqual(cell.lat, cell_lat + 0.0008)
        self.assertAlmostEqual(cell.max_lat, cell_lat + 0.004)
        self.assertAlmostEqual(cell.min_lat, cell_lat - 0.001)
        self.assertAlmostEqual(cell.lon, cell_lon - 0.0016)
        self.assertAlmostEqual(cell.max_lon, cell_lon + 0.001)
        self.assertAlmostEqual(cell.min_lon, cell_lon - 0.006)
        self.assertEqual(cell.radius, 468)
        self.assertEqual(cell.samples, 5)
        self.assertAlmostEqual(cell.weight, 5.0, 2)
Example #7
0
    def test_multiple_cells(self, geoip_db, http_session, session, source):
        now = util.utcnow()
        cell = CellShardFactory(samples=100)
        cell2 = CellShardFactory(
            radio=cell.radio,
            mcc=cell.mcc,
            mnc=cell.mnc,
            lac=cell.lac,
            cid=cell.cid + 1,
            lat=cell.lat + 1.0,
            lon=cell.lon + 1.0,
            samples=10,
        )
        session.flush()

        query = self.model_query(geoip_db,
                                 http_session,
                                 session,
                                 cells=[cell, cell2])
        results = source.search(query)
        self.check_model_results(
            results,
            [cell],
            lat=cell.lat + 0.3333333,
            lon=cell.lon + 0.3333333,
            accuracy=CELL_MAX_ACCURACY,
        )
        assert results.best().score == station_score(
            cell, now) + station_score(cell2, now)
Example #8
0
    def test_database_error(self, db_errors=0):
        cells = [
            CellShardFactory.build(radio=Radio.gsm),
            CellShardFactory.build(radio=Radio.wcdma),
            CellShardFactory.build(radio=Radio.lte),
        ]
        wifis = WifiShardFactory.build_batch(2)

        for model in (CellArea, CellOCID, CellAreaOCID):
            self.session.execute(text('drop table %s;' % model.__tablename__))
        for name in set([cell.__tablename__ for cell in cells]):
            self.session.execute(text('drop table %s;' % name))
        for name in set([wifi.__tablename__ for wifi in wifis]):
            self.session.execute(text('drop table %s;' % name))

        query = self.model_query(cells=cells, wifis=wifis)
        res = self._call(body=query, ip=self.test_ip)
        self.check_response(res, 'ok')
        self.check_stats(counter=[
            ('request', [self.metric_path, 'method:post', 'status:200']),
        ], timer=[
            ('request', [self.metric_path, 'method:post']),
        ])
        if self.apikey_metrics:
            self.check_stats(counter=[
                (self.metric_type + '.result',
                    ['key:test', 'region:GB', 'fallback_allowed:false',
                     'accuracy:high', 'status:miss']),
            ])

        self.check_raven([('ProgrammingError', db_errors)])
Example #9
0
    def test_local_export(self, celery, session):
        now = util.utcnow()
        today = now.date()
        long_ago = now - timedelta(days=367)
        cell_fixture_fields = ("radio", "cid", "lat", "lon", "mnc", "mcc", "lac")
        base_cell = CellShardFactory.build(radio=Radio.wcdma)
        cell_key = {
            "radio": Radio.wcdma,
            "mcc": base_cell.mcc,
            "mnc": base_cell.mnc,
            "lac": base_cell.lac,
        }
        cells = set()

        for cid in range(190, 200):
            cell = dict(cid=cid, lat=base_cell.lat, lon=base_cell.lon, **cell_key)
            CellShardFactory(**cell)
            cell["lat"] = "%.7f" % cell["lat"]
            cell["lon"] = "%.7f" % cell["lon"]

            cell["radio"] = "UMTS"
            cell_strings = [(field, str(value)) for (field, value) in cell.items()]
            cell_tuple = tuple(sorted(cell_strings))
            cells.add(cell_tuple)

        # add one incomplete / unprocessed cell
        CellShardFactory(cid=210, lat=None, lon=None, **cell_key)
        # add one really old cell
        CellShardFactory(
            cid=220,
            created=long_ago,
            modified=long_ago,
            last_seen=long_ago.date(),
            **cell_key,
        )
        session.commit()

        with util.selfdestruct_tempdir() as temp_dir:
            path = os.path.join(temp_dir, "export.csv.gz")
            write_stations_to_csv(session, path, today)

            with util.gzip_open(path, "r") as gzip_wrapper:
                with gzip_wrapper as gzip_file:
                    reader = csv.DictReader(gzip_file, CELL_FIELDS)

                    header = next(reader)
                    assert "area" in header.values()

                    exported_cells = set()
                    for exported_cell in reader:
                        exported_cell_filtered = [
                            (field, value)
                            for (field, value) in exported_cell.items()
                            if field in cell_fixture_fields
                        ]
                        exported_cell = tuple(sorted(exported_cell_filtered))
                        exported_cells.add(exported_cell)

                    assert cells == exported_cells
Example #10
0
    def test_cell(self):
        now = util.utcnow()
        cell = CellShardFactory(samples=10)
        self.session.flush()

        query = self.model_query(cells=[cell])
        results = self.source.search(query)
        self.check_model_results(results, [cell])
        self.assertAlmostEqual(results.best().score, cell.score(now), 4)
Example #11
0
    def test_cell_geoip_mismatch(self, app, session):
        # UK GeoIP with ambiguous US mcc
        uk_cell = CellShardFactory.build(mcc=234)
        us_cell = CellShardFactory(mcc=310)
        session.flush()

        query = self.model_query(cells=[us_cell])
        res = self._call(app, body=query, ip=self.test_ip)
        self.check_model_response(res, uk_cell, region="GB", fallback="ipf")
Example #12
0
    def test_update(self):
        now = util.utcnow()
        invalid_key = dict(lac=None, cid=None)
        observations = []

        def obs_factory(**kw):
            obs = CellObservationFactory.build(**kw)
            if obs is not None:
                observations.append(obs)

        cell1 = CellShardFactory(samples=3, weight=3.0)
        lat1, lon1 = (cell1.lat, cell1.lon)
        key1 = dict(radio=cell1.radio, 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(created=now, **invalid_key)
        obs_factory(created=now, **invalid_key)

        cell2 = CellShardFactory(lat=lat1 + 1.0,
                                 lon=lon1 + 1.0,
                                 samples=3,
                                 weight=3.0)
        lat2, lon2 = (cell2.lat, cell2.lon)
        key2 = dict(radio=cell2.radio, lac=cell2.lac, cid=cell2.cid)
        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 = CellShardFactory(samples=100000, weight=100000.0)
        lat3, lon3 = (cell3.lat, cell3.lon)
        key3 = dict(radio=cell3.radio, lac=cell3.lac, cid=cell3.cid)
        for i in range(10):
            obs_factory(lat=lat3 + 0.5, lon=lon3 + 0.5, **key3)

        self.session.commit()
        self._queue_and_update_cell(observations)

        shard = CellShard.shard_model(cell1.cellid)
        found = (self.session.query(shard).filter(
            shard.cellid == cell1.cellid)).one()
        self.assertAlmostEqual(found.lat, lat1 + 0.001667, 6)
        self.assertAlmostEqual(found.lon, lon1 + 0.0025, 6)

        shard = CellShard.shard_model(cell2.cellid)
        found = (self.session.query(shard).filter(
            shard.cellid == cell2.cellid)).one()
        self.assertAlmostEqual(found.lat, lat2 + 0.0008, 6)
        self.assertAlmostEqual(found.lon, lon2 + 0.0016, 6)

        shard = CellShard.shard_model(cell3.cellid)
        found = (self.session.query(shard).filter(
            shard.cellid == cell3.cellid)).one()
        expected_lat = ((lat3 * 10000) + (lat3 + 0.5) * 10) / 10010
        expected_lon = ((lon3 * 10000) + (lon3 + 0.5) * 10) / 10010
        self.assertAlmostEqual(found.lat, expected_lat, 7)
        self.assertAlmostEqual(found.lon, expected_lon, 7)
Example #13
0
    def test_cells_over_geoip(self, app, session):
        # UK GeoIP with multiple US cells
        us_cell1 = CellShardFactory(radio=Radio.gsm, mcc=310, samples=100)
        us_cell2 = CellShardFactory(radio=Radio.lte, mcc=311, samples=100)
        session.flush()

        query = self.model_query(cells=[us_cell1, us_cell2])
        res = self._call(app, body=query, ip=self.test_ip)
        self.check_model_response(res, us_cell1, region="US")
Example #14
0
    def add_reports(self, num=1, blue_factor=0, cell_factor=1, wifi_factor=2,
                    blue_key=None, cell_mcc=None, wifi_key=None,
                    api_key='test', lat=None, lon=None):
        reports = []
        for i in range(num):
            pos = CellShardFactory.build()
            report = {
                'timestamp': time.time() * 1000.0,
                'position': {},
                'bluetoothBeacons': [],
                'cellTowers': [],
                'wifiAccessPoints': [],
            }
            report['position']['latitude'] = lat or pos.lat
            report['position']['longitude'] = lon or pos.lon
            report['position']['accuracy'] = 17.0 + i

            blues = BlueShardFactory.build_batch(blue_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for blue in blues:
                blue_data = {
                    'macAddress': blue_key or blue.mac,
                    'signalStrength': -100 + i,
                }
                report['bluetoothBeacons'].append(blue_data)

            cells = CellShardFactory.build_batch(cell_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for cell in cells:
                cell_data = {
                    'radioType': cell.radio.name,
                    'mobileCountryCode': cell_mcc or cell.mcc,
                    'mobileNetworkCode': cell.mnc,
                    'locationAreaCode': cell.lac,
                    'cellId': cell.cid,
                    'primaryScramblingCode': cell.psc,
                    'signalStrength': -110 + i,
                }
                report['cellTowers'].append(cell_data)

            wifis = WifiShardFactory.build_batch(wifi_factor,
                                                 lat=pos.lat, lon=pos.lon)
            for wifi in wifis:
                wifi_data = {
                    'macAddress': wifi_key or wifi.mac,
                    'signalStrength': -90 + i,
                    'ssid': 'my-wifi',
                }
                report['wifiAccessPoints'].append(wifi_data)

            reports.append(report)

        items = [{'api_key': api_key, 'report': rep} for rep in reports]

        self.queue.enqueue(items)
        return reports
Example #15
0
    def test_cell_geoip_mismatch(self):
        # UK GeoIP with ambiguous US mcc
        uk_cell = CellShardFactory.build(mcc=234)
        us_cell = CellShardFactory(mcc=310)
        self.session.flush()

        query = self.model_query(cells=[us_cell])
        res = self._call(body=query, ip=self.test_ip)
        self.check_model_response(res, uk_cell, region='GB', fallback='ipf')
        self.check_db_calls(rw=0, ro=2)
Example #16
0
    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)
Example #17
0
    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)
Example #18
0
    def test_cell(self, geoip_db, http_session, session, source, stats):
        now = util.utcnow()
        cell = CellShardFactory(samples=10)
        session.flush()

        query = self.model_query(
            geoip_db, http_session, session, stats,
            cells=[cell])
        results = source.search(query)
        self.check_model_results(results, [cell])
        assert results.best().score == cell.score(now)
Example #19
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')

        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])
Example #20
0
    def test_cdma_cell(self, app, session):
        """A CDMA radio is not an error, but the information is ignored."""
        cell = CellShardFactory(radio=Radio.gsm, radius=15000)
        cell2 = CellShardFactory(
            radio=Radio.gsm, radius=35000, lat=cell.lat + 0.0002, lon=cell.lon
        )
        cell2.radio = Radio.cdma
        session.flush()

        query = self.model_query(cells=[cell, cell2])
        res = self._call(app, body=query)
        self.check_model_response(res, cell)
Example #21
0
    def test_cdma_cell(self):
        # Specifying a CDMA radio type works,
        # but the information is ignored.
        cell = CellShardFactory(radio=Radio.gsm, radius=15000)
        cell2 = CellShardFactory(radio=Radio.gsm, radius=35000,
                                 lat=cell.lat + 0.0002, lon=cell.lon)
        cell2.radio = Radio.cdma
        self.session.flush()

        query = self.model_query(cells=[cell, cell2])
        res = self._call(body=query)
        self.check_model_response(res, cell)
Example #22
0
    def test_local_export(self):
        cell_fixture_fields = ('radio', 'cid', 'lat', 'lon', 'mnc', 'mcc',
                               'lac')
        base_cell = CellShardFactory.build(radio=Radio.wcdma)
        cell_key = {
            'radio': Radio.wcdma,
            'mcc': base_cell.mcc,
            'mnc': base_cell.mnc,
            'lac': base_cell.lac
        }
        cells = set()

        for cid in range(190, 200):
            cell = dict(cid=cid,
                        lat=base_cell.lat,
                        lon=base_cell.lon,
                        **cell_key)
            CellShardFactory(**cell)
            cell['lat'] = '%.7f' % cell['lat']
            cell['lon'] = '%.7f' % cell['lon']

            cell['radio'] = 'UMTS'
            cell_strings = [(field, str(value))
                            for (field, value) in cell.items()]
            cell_tuple = tuple(sorted(cell_strings))
            cells.add(cell_tuple)

        # add one incomplete / unprocessed cell
        CellShardFactory(cid=210, lat=None, lon=None, **cell_key)
        self.session.commit()

        with util.selfdestruct_tempdir() as temp_dir:
            path = os.path.join(temp_dir, 'export.csv.gz')
            write_stations_to_csv(self.session, path)

            with util.gzip_open(path, 'r') as gzip_wrapper:
                with gzip_wrapper as gzip_file:
                    reader = csv.DictReader(gzip_file, CELL_FIELDS)

                    header = six.next(reader)
                    self.assertTrue('area' in header.values())

                    exported_cells = set()
                    for exported_cell in reader:
                        exported_cell_filtered = [
                            (field, value)
                            for (field, value) in exported_cell.items()
                            if field in cell_fixture_fields
                        ]
                        exported_cell = tuple(sorted(exported_cell_filtered))
                        exported_cells.add(exported_cell)

                    self.assertEqual(cells, exported_cells)
Example #23
0
    def test_local_export(self, celery, session):
        now = util.utcnow()
        today = now.date()
        long_ago = now - timedelta(days=367)
        cell_fixture_fields = (
            'radio', 'cid', 'lat', 'lon', 'mnc', 'mcc', 'lac')
        base_cell = CellShardFactory.build(radio=Radio.wcdma)
        cell_key = {'radio': Radio.wcdma, 'mcc': base_cell.mcc,
                    'mnc': base_cell.mnc, 'lac': base_cell.lac}
        cells = set()

        for cid in range(190, 200):
            cell = dict(cid=cid, lat=base_cell.lat,
                        lon=base_cell.lon, **cell_key)
            CellShardFactory(**cell)
            cell['lat'] = '%.7f' % cell['lat']
            cell['lon'] = '%.7f' % cell['lon']

            cell['radio'] = 'UMTS'
            cell_strings = [
                (field, str(value)) for (field, value) in cell.items()]
            cell_tuple = tuple(sorted(cell_strings))
            cells.add(cell_tuple)

        # add one incomplete / unprocessed cell
        CellShardFactory(cid=210, lat=None, lon=None, **cell_key)
        # add one really old cell
        CellShardFactory(cid=220, created=long_ago, modified=long_ago,
                         last_seen=long_ago.date(), **cell_key)
        session.commit()

        with util.selfdestruct_tempdir() as temp_dir:
            path = os.path.join(temp_dir, 'export.csv.gz')
            write_stations_to_csv(session, path, today)

            with util.gzip_open(path, 'r') as gzip_wrapper:
                with gzip_wrapper as gzip_file:
                    reader = csv.DictReader(gzip_file, CELL_FIELDS)

                    header = six.next(reader)
                    assert 'area' in header.values()

                    exported_cells = set()
                    for exported_cell in reader:
                        exported_cell_filtered = [
                            (field, value) for (field, value)
                            in exported_cell.items()
                            if field in cell_fixture_fields]
                        exported_cell = tuple(sorted(exported_cell_filtered))
                        exported_cells.add(exported_cell)

                    assert cells == exported_cells
Example #24
0
    def test_multiple_cells(self):
        cell = CellShardFactory()
        cell2 = CellShardFactory(radio=cell.radio, mcc=cell.mcc, mnc=cell.mnc,
                                 lac=cell.lac, cid=cell.cid + 1,
                                 lat=cell.lat + 1.0, lon=cell.lon + 1.0)
        self.session.flush()

        query = self.model_query(cells=[cell, cell2])
        result = self.source.search(query)
        self.check_model_result(
            result, cell,
            lat=cell.lat + 0.5, lon=cell.lon + 0.5,
            accuracy=CELL_MAX_ACCURACY)
Example #25
0
    def test_cdma_cell(self):
        # Specifying a CDMA radio type works,
        # but the information is ignored.
        cell = CellShardFactory(radio=Radio.gsm, radius=15000)
        cell2 = CellShardFactory(radio=Radio.gsm,
                                 radius=35000,
                                 lat=cell.lat + 0.0002,
                                 lon=cell.lon)
        cell2.radio = Radio.cdma
        self.session.flush()

        query = self.model_query(cells=[cell, cell2])
        res = self._call(body=query)
        self.check_model_response(res, cell)
Example #26
0
    def test_inconsistent_cell_radio_type(self, app, session):
        cell = CellShardFactory(
            radio=Radio.wcdma, radius=15000, samples=10)
        cell2 = CellShardFactory(
            radio=Radio.gsm, radius=35000, samples=5,
            lat=cell.lat + 0.0002, lon=cell.lon)
        session.flush()

        query = self.model_query(cells=[cell, cell2])
        query['radioType'] = Radio.lte.name
        query['cellTowers'][0]['radio'] = 'lte'

        res = self._call(app, body=query)
        self.check_model_response(res, cell)
Example #27
0
 def test_get_cell_multi(self, cache, stats):
     cells = CellShardFactory.build_batch(2)
     query = self._query(cell=self.cell_model_query(cells))
     assert cache.get(query) is None
     stats.check(counter=[
         ('locate.fallback.cache', 1, 1, ['status:bypassed']),
     ])
Example #28
0
 def test_cell(self):
     cell = CellShardFactory.build(radio=Radio.lte)
     query = Query(cell=[{
         'radioType': cell.radio,
         'mobileCountryCode': cell.mcc,
         'mobileNetworkCode': cell.mnc,
         'locationAreaCode': cell.lac,
         'cellId': cell.cid,
         'age': 1200,
         'asu': None,
         'primaryScramblingCode': 5,
         'signalStrength': -70,
         'timingAdvance': 15,
         'unknown_field': 'foo'
     }])
     data = OUTBOUND_SCHEMA.deserialize(query.json())
     assert (data == {
         'cellTowers': [{
             'radioType': cell.radio.name,
             'mobileCountryCode': cell.mcc,
             'mobileNetworkCode': cell.mnc,
             'locationAreaCode': cell.lac,
             'cellId': cell.cid,
             'primaryScramblingCode': 5,
             'age': 1200,
             'signalStrength': -70,
             'timingAdvance': 15,
         }],
         'fallbacks': {
             'lacf': True
         },
     })
Example #29
0
    def test_cell(self):
        cell = CellShardFactory.build(radio=Radio.lte)
        cell_query = self.cell_model_query([cell])
        query = Query(cell=cell_query)

        assert len(query.cell) == 1
        assert query.expected_accuracy is DataAccuracy.medium
        assert query.geoip_only is False

        query_cell = query.cell[0]
        for key, value in cell_query[0].items():
            query_value = getattr(query_cell, key, None)
            if key == 'radioType':
                assert query_value is cell.radio
            else:
                assert query_value == value

        assert len(query.cell_area) == 1
        query_area = query.cell_area[0]
        for key, value in cell_query[0].items():
            query_value = getattr(query_area, key, None)
            if key == 'radioType':
                assert query_value is cell.radio
            elif key in ('cellId', 'primaryScramblingCode'):
                pass
            else:
                assert query_value == value
Example #30
0
 def test_get_cell_multi(self):
     cells = CellShardFactory.build_batch(2)
     query = Query(cell=self.cell_model_query(cells))
     self.assertEqual(self.cache.get(query), None)
     self.check_stats(counter=[
         ('locate.fallback.cache', 1, 1, ['status:bypassed']),
     ])
Example #31
0
    def test_dont_recache(self, geoip_db, http_session, session, source,
                          stats):
        cell = CellShardFactory.build()
        mock_redis_client = self._mock_redis_client()
        mock_redis_client.mget.return_value = [self.fallback_cached_result]

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri('POST',
                                      requests_mock.ANY,
                                      json=self.fallback_result)

            with mock.patch.object(source.cache, 'redis_client',
                                   mock_redis_client):
                query = self.model_query(geoip_db,
                                         http_session,
                                         session,
                                         stats,
                                         cells=[cell])
                results = source.search(query)
                self.check_model_results(results, [self.fallback_model])

            assert mock_redis_client.mget.called
            assert not mock_redis_client.mset.called

        stats.check(counter=[
            ('locate.fallback.cache', ['status:hit']),
        ])
Example #32
0
 def test_cell_geoip_mismatch(self):
     # UK GeoIP with US mcc
     cell = CellShardFactory.create(mcc=310)
     query = self.model_query(cells=[cell])
     res = self._call(body=query, ip=self.test_ip)
     self.check_model_response(res, cell, region='US')
     self.check_db_calls(rw=0, ro=0)
Example #33
0
    def test_api_key_disallows(self):
        api_key = ApiKeyFactory.build(allow_fallback=False)
        cells = CellShardFactory.build_batch(2)
        wifis = WifiShardFactory.build_batch(2)

        query = self.model_query(cells=cells, wifis=wifis, api_key=api_key)
        self.check_should_search(query, False)
Example #34
0
    def test_cache_empty_result(self):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri('POST',
                                      requests_mock.ANY,
                                      json=LocationNotFound.json_body(),
                                      status_code=404)

            query = self.model_query(cells=[cell])
            results = self.source.search(query)
            self.check_model_results(results, None)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:miss']),
                ('locate.fallback.lookup',
                 ['fallback_name:fall', 'status:404']),
            ])

            query = self.model_query(cells=[cell])
            results = self.source.search(query)
            self.check_model_results(results, None)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:hit']),
                ('locate.fallback.lookup',
                 ['fallback_name:fall', 'status:404']),
            ])
Example #35
0
 def test_get_cell_multi(self):
     cells = CellShardFactory.build_batch(2)
     query = self._query(cell=self.cell_model_query(cells))
     self.assertEqual(self.cache.get(query), None)
     self.check_stats(counter=[
         ('locate.fallback.cache', 1, 1, ['status:bypassed']),
     ])
Example #36
0
    def test_success(self):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri('POST',
                                      requests_mock.ANY,
                                      json=self.fallback_result)

            query = self.model_query(
                cells=[cell],
                fallback={
                    'lacf': True,
                    'ipf': False,
                },
            )
            results = self.source.search(query)
            self.check_model_results(results, [self.fallback_model])
            self.assertAlmostEqual(results.best().score, 5.0, 4)

            request_json = mock_request.request_history[0].json()

        self.assertEqual(request_json['fallbacks'], {'lacf': True})
        self.check_stats(counter=[
            ('locate.fallback.lookup', ['fallback_name:fall', 'status:200']),
        ],
                         timer=[
                             ('locate.fallback.lookup', ['fallback_name:fall'
                                                         ]),
                         ])
Example #37
0
    def test_success(self):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            query = self.model_query(
                cells=[cell],
                fallback={
                    'lacf': True,
                    'ipf': False,
                },
            )
            result = self.source.search(query)
            self.check_model_result(result, self.fallback_model)

            request_json = mock_request.request_history[0].json()

        self.assertEqual(request_json['fallbacks'], {'lacf': True})
        self.check_stats(counter=[
            ('locate.fallback.lookup', ['status:200']),
        ], timer=[
            'locate.fallback.lookup',
        ])
Example #38
0
    def test_api_key_disallows(self):
        api_key = ApiKeyFactory.build(allow_fallback=False)
        cells = CellShardFactory.build_batch(2)
        wifis = WifiShardFactory.build_batch(2)

        query = self.model_query(cells=cells, wifis=wifis, api_key=api_key)
        self.check_should_search(query, False)
Example #39
0
    def test_set_cache_redis_failure(self):
        cell = CellShardFactory.build()
        mock_redis_client = self._mock_redis_client()
        mock_redis_client.mget.return_value = []
        mock_redis_client.mset.side_effect = RedisError()
        mock_redis_client.expire.side_effect = RedisError()
        mock_redis_client.execute.side_effect = RedisError()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            with mock.patch.object(self.source.cache, 'redis_client',
                                   mock_redis_client):
                query = self.model_query(cells=[cell])
                result = self.source.search(query)
                self.check_model_result(result, self.fallback_model)

            self.assertTrue(mock_redis_client.mget.called)
            self.assertTrue(mock_redis_client.mset.called)
            self.assertTrue(mock_request.called)

        self.check_stats(counter=[
            ('locate.fallback.cache', ['status:miss']),
        ])
Example #40
0
    def test_cache_single_cell(self):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            query = self.model_query(cells=[cell])
            query.cell[0].signal = -77
            result = self.source.search(query)
            self.check_model_result(result, self.fallback_model)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:miss']),
                ('locate.fallback.lookup', ['status:200']),
            ], timer=[
                'locate.fallback.lookup',
            ])

            # vary the signal strength, not part of cache key
            query.cell[0].signal = -82
            result = self.source.search(query)
            self.check_model_result(result, self.fallback_model)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:hit']),
                ('locate.fallback.lookup', ['status:200']),
            ], timer=[
                'locate.fallback.lookup',
            ])
Example #41
0
 def test_cell_ambiguous(self):
     # cell with ambiguous mcc to region mapping
     cell = CellShardFactory.create(mcc=234)
     query = self.model_query(cells=[cell])
     res = self._call(body=query)
     self.check_model_response(res, cell, region='GB')
     self.check_db_calls(rw=0, ro=0)
Example #42
0
    def test_set_cache_redis_failure(self, geoip_db, http_session, raven,
                                     session, source, stats):
        cell = CellShardFactory.build()
        mock_redis_client = self._mock_redis_client()
        mock_redis_client.mget.return_value = []
        mock_redis_client.mset.side_effect = RedisError()
        mock_redis_client.expire.side_effect = RedisError()
        mock_redis_client.execute.side_effect = RedisError()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri('POST',
                                      requests_mock.ANY,
                                      json=self.fallback_result)

            with mock.patch.object(source.cache, 'redis_client',
                                   mock_redis_client):
                query = self.model_query(geoip_db,
                                         http_session,
                                         session,
                                         stats,
                                         cells=[cell])
                results = source.search(query)
                self.check_model_results(results, [self.fallback_model])

            assert mock_redis_client.mget.called
            assert mock_redis_client.mset.called
            assert mock_request.called

        raven.check([('RedisError', 1)])
        stats.check(counter=[
            ('locate.fallback.cache', ['status:miss']),
        ])
Example #43
0
    def test_success(self, geoip_db, http_session, session, source, stats):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri('POST',
                                      requests_mock.ANY,
                                      json=self.fallback_result)

            query = self.model_query(
                geoip_db,
                http_session,
                session,
                stats,
                cells=[cell],
                fallback={
                    'lacf': True,
                    'ipf': False,
                },
            )
            results = source.search(query)
            self.check_model_results(results, [self.fallback_model])
            assert results.best().score == 5.0

            request_json = mock_request.request_history[0].json()

        assert request_json['fallbacks'] == {'lacf': True}
        stats.check(counter=[
            ('locate.fallback.lookup', ['fallback_name:fall', 'status:200']),
        ],
                    timer=[
                        ('locate.fallback.lookup', ['fallback_name:fall']),
                    ])
Example #44
0
    def test_cache_empty_result(self):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST',
                requests_mock.ANY,
                json=LocationNotFound.json_body(),
                status_code=404
            )

            query = self.model_query(cells=[cell])
            result = self.source.search(query)
            self.check_model_result(result, None)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:miss']),
                ('locate.fallback.lookup', ['status:404']),
            ])

            query = self.model_query(cells=[cell])
            result = self.source.search(query)
            self.check_model_result(result, None)

            self.assertEqual(mock_request.call_count, 1)
            self.check_stats(counter=[
                ('locate.fallback.cache', ['status:hit']),
                ('locate.fallback.lookup', ['status:404']),
            ])
Example #45
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])
Example #46
0
    def test_cell(self):
        cell = CellShardFactory.build(radio=Radio.lte)
        cell_query = self.cell_model_query([cell])
        query = Query(cell=cell_query)

        self.assertEqual(len(query.cell), 1)
        self.assertEqual(query.expected_accuracy, DataAccuracy.medium)

        query_cell = query.cell[0]
        for key, value in cell_query[0].items():
            query_value = getattr(query_cell, key, None)
            if key == 'radio':
                self.assertEqual(query_value, cell.radio)
            else:
                self.assertEqual(query_value, value)

        self.assertEqual(len(query.cell_area), 1)
        query_area = query.cell_area[0]
        for key, value in cell_query[0].items():
            query_value = getattr(query_area, key, None)
            if key == 'radio':
                self.assertEqual(query_value, cell.radio)
            elif key in ('cid', 'psc'):
                pass
            else:
                self.assertEqual(query_value, value)
Example #47
0
 def test_cell_geoip_mismatch(self):
     # UK GeoIP with US mcc
     cell = CellShardFactory.create(mcc=310)
     query = self.model_query(cells=[cell])
     res = self._call(body=query, ip=self.test_ip)
     self.check_model_response(res, cell, region='US')
     self.check_db_calls(rw=0, ro=0)
Example #48
0
    def test_blocklist(self):
        now = util.utcnow()
        today = now.date()
        observations = CellObservationFactory.build_batch(3)
        obs = observations[0]
        CellShardFactory(
            radio=obs.radio,
            mcc=obs.mcc,
            mnc=obs.mnc,
            lac=obs.lac,
            cid=obs.cid,
            created=now,
            block_first=today - timedelta(days=10),
            block_last=today,
            block_count=1,
        )
        self.session.commit()
        self._queue_and_update(observations)

        blocks = []
        for obs in observations:
            shard = CellShard.shard_model(obs.cellid)
            cell = (self.session.query(shard).filter(
                shard.cellid == obs.cellid)).one()
            if cell.blocked():
                blocks.append(cell)

        self.assertEqual(len(blocks), 1)
        self.check_statcounter(StatKey.cell, 2)
        self.check_statcounter(StatKey.unique_cell, 2)
Example #49
0
    def test_set_cache_redis_failure(self, geoip_db, http_session,
                                     raven, session, source, stats):
        cell = CellShardFactory.build()
        mock_redis_client = _mock_redis_client()
        mock_redis_client.mget.return_value = []
        mock_redis_client.mset.side_effect = RedisError()
        mock_redis_client.expire.side_effect = RedisError()
        mock_redis_client.execute.side_effect = RedisError()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            with mock.patch.object(source.caches[DEFAULT_SCHEMA],
                                   'redis_client',
                                   mock_redis_client):
                query = self.model_query(
                    geoip_db, http_session, session, stats,
                    cells=[cell])
                results = source.search(query)
                self.check_model_results(results, [self.fallback_model])

            assert mock_redis_client.mget.called
            assert mock_redis_client.mset.called
            assert mock_request.called

        raven.check([('RedisError', 1)])
        stats.check(counter=[
            ('locate.fallback.cache', [self.fallback_tag, 'status:miss']),
        ])
Example #50
0
 def test_cell_ambiguous(self):
     # cell with ambiguous mcc to region mapping
     cell = CellShardFactory.create(mcc=234)
     query = self.model_query(cells=[cell])
     res = self._call(body=query)
     self.check_model_response(res, cell, region='GB')
     self.check_db_calls(rw=0, ro=0)
Example #51
0
 def test_cell(self):
     cell = CellShardFactory.build(radio=Radio.lte)
     query = Query(cell=[
         {'radioType': cell.radio,
          'mobileCountryCode': cell.mcc,
          'mobileNetworkCode': cell.mnc,
          'locationAreaCode': cell.lac,
          'cellId': cell.cid,
          'age': 1200,
          'signalStrength': -70,
          'timingAdvance': 15,
          'unknown_field': 'foo'}])
     data = self._call(query.json())
     assert (data == {
         'cellTowers': [{
             'radioType': cell.radio.name,
             'mobileCountryCode': cell.mcc,
             'mobileNetworkCode': cell.mnc,
             'locationAreaCode': cell.lac,
             'cellId': cell.cid,
             'age': 1200,
             'signalStrength': -70,
             'timingAdvance': 15,
         }],
         'considerIp': False,
     })
Example #52
0
    def test_dont_recache(self, geoip_db, http_session,
                          session, source, stats):
        cell = CellShardFactory.build()
        mock_redis_client = _mock_redis_client()
        mock_redis_client.mget.return_value = [self.fallback_cached_result]

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            with mock.patch.object(source.caches[DEFAULT_SCHEMA],
                                   'redis_client',
                                   mock_redis_client):
                query = self.model_query(
                    geoip_db, http_session, session, stats,
                    cells=[cell])
                results = source.search(query)
                self.check_model_results(results, [self.fallback_model])

            assert mock_redis_client.mget.called
            assert not mock_redis_client.mset.called

        stats.check(counter=[
            ('locate.fallback.cache', [self.fallback_tag, 'status:hit']),
        ])
Example #53
0
 def test_cell(self):
     cell = CellShardFactory.build(radio=Radio.lte)
     query = Query(cell=[
         {'radioType': cell.radio,
          'mobileCountryCode': cell.mcc,
          'mobileNetworkCode': cell.mnc,
          'locationAreaCode': cell.lac,
          'cellId': cell.cid,
          'asu': 17,
          'primaryScramblingCode': 5,
          'signalStrength': -70,
          'timingAdvance': 15,
          'unknown_field': 'foo'}])
     data = self._call(query.json())
     assert (data == {
         'cells': [{
             'radio': cell.radio.name,
             'mcc': cell.mcc,
             'mnc': cell.mnc,
             'lac': cell.lac,
             'cid': cell.cid,
             'asu': 17,
             'psc': 5,
             'signal': -70,
             'tA': 15,
         }],
         'fallbacks': {'lacf': True},
         'token': None,
     })
Example #54
0
    def test_success(self, geoip_db, http_session, session, source, stats):
        cell = CellShardFactory.build()

        with requests_mock.Mocker() as mock_request:
            mock_request.register_uri(
                'POST', requests_mock.ANY, json=self.fallback_result)

            query = self.model_query(
                geoip_db, http_session, session, stats,
                cells=[cell],
                fallback={
                    'lacf': True,
                    'ipf': False,
                },
            )
            results = source.search(query)
            self.check_model_results(results, [self.fallback_model])
            assert results.best().score == 5.0

            request_json = mock_request.request_history[0].json()

        self._check_success_fallbacks(request_json)
        stats.check(counter=[
            ('locate.fallback.lookup', [self.fallback_tag, 'status:200']),
        ], timer=[
            ('locate.fallback.lookup', [self.fallback_tag]),
        ])
Example #55
0
 def test_medium_hit(self):
     cells = CellShardFactory.build_batch(1)
     self._make_query(self._make_result(accuracy=50000.0), cell=cells)
     self.check_stats(counter=[
         ('locate.result',
             ['key:key', 'region:none', 'fallback_allowed:false',
              'accuracy:medium', 'status:hit']),
     ])
Example #56
0
    def test_mixed_cell_wifi(self):
        cells = CellShardFactory.build_batch(1)
        wifis = WifiShardFactory.build_batch(2)

        query = Query(
            cell=self.cell_model_query(cells),
            wifi=self.wifi_model_query(wifis))
        self.assertEqual(query.expected_accuracy, DataAccuracy.high)
Example #57
0
 def test_cell_area_duplicated(self):
     cell = CellShardFactory.build()
     cell_query = self.cell_model_query([cell, cell, cell])
     cell_query[1]['cid'] += 2
     cell_query[2]['cid'] += 1
     query = Query(cell=cell_query)
     self.assertEqual(len(query.cell), 3)
     self.assertEqual(len(query.cell_area), 1)
Example #58
0
 def _one_cell_query(self, radio=True):
     cell = CellShardFactory.build()
     query = {'lat': cell.lat, 'lon': cell.lon,
              'cell': [{'mcc': cell.mcc, 'mnc': cell.mnc,
                        'lac': cell.lac, 'cid': cell.cid}]}
     if radio:
         query['cell'][0]['radio'] = cell.radio.name
     return (cell, query)