예제 #1
0
    def test_stats(self):
        self.session.add(ApiKey(valid_key='e5444-794', log=True))
        self.session.flush()

        self.add_reports(3, email='secretemail@localhost',
                         ip=self.geoip_data['London']['ip'])
        self.add_reports(6, api_key='e5444-794')
        self.add_reports(3, api_key=None)

        schedule_export_reports.delay().get()
        update_cell.delay().get()
        update_wifi.delay().get()

        self.check_stats(counter=[
            ('data.export.batch', 1, 1, ['key:internal']),
            ('data.report.upload', 2, 3),
            ('data.report.upload', 1, 3, ['key:test']),
            ('data.report.upload', 1, 6, ['key:e5444-794']),
            ('data.observation.insert', 1, 12, ['type:cell']),
            ('data.observation.insert', 1, 24, ['type:wifi']),
            ('data.observation.upload', 1, 3, ['type:cell', 'key:test']),
            ('data.observation.upload', 1, 6, ['type:wifi', 'key:test']),
            ('data.observation.upload', 0, ['type:cell', 'key:no_key']),
            ('data.observation.upload', 1, 6, ['type:cell', 'key:e5444-794']),
            ('data.observation.upload', 1, 12, ['type:wifi', 'key:e5444-794']),
        ])
예제 #2
0
    def test_blacklist(self):
        utcnow = util.utcnow()

        bad_wifi = WifiFactory.build()
        good_wifi = WifiFactory.build()
        black = WifiBlacklist(time=utcnow, count=1, key=bad_wifi.key)
        self.session.add(black)
        self.session.flush()

        obs = dict(lat=good_wifi.lat, lon=good_wifi.lon)
        entries = [
            {'key': good_wifi.key},
            {'key': good_wifi.key},
            {'key': bad_wifi.key},
        ]
        for entry in entries:
            entry.update(obs)

        result = insert_measures_wifi.delay(entries)
        self.assertEqual(result.get(), 2)

        self.assertEqual(self.data_queue.size(), 2)
        update_wifi.delay().get()

        wifis = self.session.query(Wifi).all()
        self.assertEqual(len(wifis), 1)
        self._compare_sets([w.key for w in wifis], [good_wifi.key])

        self.check_statcounter(StatKey.wifi, 2)
        self.check_statcounter(StatKey.unique_wifi, 1)
예제 #3
0
    def test_country(self):
        obs = []
        obs_factory = WifiObservationFactory
        wifi1 = WifiShardFactory(lat=55.807, lon=1.7465, country='GB')
        obs.append(obs_factory(
            key=wifi1.mac,
            lat=wifi1.lat,
            lon=wifi1.lon + 0.001,
        ))
        wifi2 = WifiShardFactory(lat=50.022, lon=1.7465, country='GB')
        obs.append(obs_factory(
            key=wifi2.mac,
            lat=wifi2.lat,
            lon=wifi2.lon + 0.001,
        ))

        self.data_queue.enqueue(obs)
        self.session.commit()
        update_wifi.delay().get()

        wifi1 = self.session.query(wifi1.__class__).get(wifi1.mac)
        self.assertEqual(wifi1.block_count, 0)
        self.assertEqual(wifi1.country, None)
        wifi2 = self.session.query(wifi2.__class__).get(wifi2.mac)
        self.assertEqual(wifi1.block_count, 0)
        self.assertEqual(wifi2.country, 'FR')
예제 #4
0
    def test_temp_blocked_admitted_again(self):
        now = util.utcnow()
        last_week = now - TEMPORARY_BLOCKLIST_DURATION - timedelta(days=1)

        obs = WifiObservationFactory()
        WifiShardFactory(
            mac=obs.mac,
            lat=None,
            lon=None,
            samples=0,
            created=last_week,
            modified=last_week,
            block_first=last_week.date(),
            block_last=last_week.date(),
            block_count=1)
        self.session.flush()

        # add a new entry for the previously blocked wifi
        self.data_queue.enqueue([obs])
        self.assertEqual(self.data_queue.size(), 1)
        update_wifi.delay().get()

        # the wifi was inserted again
        shard = WifiShard.shard_model(obs.mac)
        wifis = self.session.query(shard).all()
        self.assertEqual(len(wifis), 1)
        wifi = wifis[0]
        self.assertEqual(wifi.created.date(), last_week.date())
        self.assertAlmostEqual(wifi.lat, obs.lat)
        self.assertAlmostEqual(wifi.lon, obs.lon)
        self.assertEqual(wifi.country, 'GB')
        self.assertEqual(wifi.samples, 1)
        self.check_statcounter(StatKey.unique_wifi, 0)
예제 #5
0
    def test_stats(self):
        self.session.add(ApiKey(valid_key='e5444-794', log_submit=True))
        self.session.flush()

        self.add_reports(3, email='secretemail@localhost',
                         ip=self.geoip_data['London']['ip'])
        self.add_reports(6, api_key='e5444-794')
        self.add_reports(3, api_key=None)

        schedule_export_reports.delay().get()
        update_cell.delay().get()
        for i in range(16):
            update_wifi.delay(shard_id='%x' % i).get()

        self.check_stats(counter=[
            ('data.export.batch', 1, 1, ['key:internal']),
            ('data.report.upload', 2, 3),
            ('data.report.upload', 1, 3, ['key:test']),
            ('data.report.upload', 1, 6, ['key:e5444-794']),
            ('data.observation.insert', 1, 12, ['type:cell']),
            ('data.observation.upload', 1, 3, ['type:cell', 'key:test']),
            ('data.observation.upload', 1, 6, ['type:wifi', 'key:test']),
            ('data.observation.upload', 0, ['type:cell', 'key:no_key']),
            ('data.observation.upload', 1, 6, ['type:cell', 'key:e5444-794']),
            ('data.observation.upload', 1, 12, ['type:wifi', 'key:e5444-794']),
        ])
        # we get a variable number of statsd messages and are only
        # interested in the sum-total
        insert_msgs = [msg for msg in self.stats_client.msgs
                       if (msg.startswith('data.observation.insert') and
                           'type:wifi' in msg)]
        self.assertEqual(
            sum([int(msg.split(':')[1].split('|')[0]) for msg in insert_msgs]),
            24)
예제 #6
0
    def test_new(self):
        utcnow = util.utcnow()
        obs = WifiObservationFactory.build()
        self.data_queue.enqueue([obs])
        self.assertEqual(self.data_queue.size(), 1)
        update_wifi.delay().get()

        shard = WifiShard.shard_model(obs.mac)
        wifis = self.session.query(shard).all()
        self.assertEqual(len(wifis), 1)
        wifi = wifis[0]
        self.assertAlmostEqual(wifi.lat, obs.lat)
        self.assertAlmostEqual(wifi.max_lat, obs.lat)
        self.assertAlmostEqual(wifi.min_lat, obs.lat)
        self.assertAlmostEqual(wifi.lon, obs.lon)
        self.assertAlmostEqual(wifi.max_lon, obs.lon)
        self.assertAlmostEqual(wifi.min_lon, obs.lon)
        self.assertEqual(wifi.country, 'GB')
        self.assertEqual(wifi.radius, 0)
        self.assertEqual(wifi.samples, 1)
        self.assertEqual(wifi.created.date(), utcnow.date())
        self.assertEqual(wifi.modified.date(), utcnow.date())
        self.assertEqual(wifi.block_first, None)
        self.assertEqual(wifi.block_last, None)
        self.assertEqual(wifi.block_count, None)
예제 #7
0
    def _update_all(self):
        schedule_export_reports.delay().get()

        for shard_id in CellShard.shards().keys():
            update_cell.delay(shard_id=shard_id).get()

        for shard_id in WifiShard.shards().keys():
            update_wifi.delay(shard_id=shard_id).get()
예제 #8
0
    def _update_all(self):
        schedule_export_reports.delay().get()

        for shard_id in CellShard.shards().keys():
            update_cell.delay(shard_id=shard_id).get()

        for shard_id in WifiShard.shards().keys():
            update_wifi.delay(shard_id=shard_id).get()
예제 #9
0
    def test_blacklist_moving_wifis(self):
        now = util.utcnow()
        k1 = 'ab1234567890'
        k2 = 'bc1234567890'
        k3 = 'cd1234567890'
        k4 = 'de1234567890'
        k5 = 'ef1234567890'

        # keys k2, k3 and k4 are expected to be detected as moving
        data = [
            # a wifi with an entry but no prior position
            Wifi(key=k1, total_measures=0),
            WifiObservation(lat=1.001, lon=1.001, key=k1),
            WifiObservation(lat=1.002, lon=1.005, key=k1),
            WifiObservation(lat=1.003, lon=1.009, key=k1),
            # a wifi with a prior known position
            Wifi(lat=2.0, lon=2.0, key=k2, total_measures=1),
            WifiObservation(lat=2.01, lon=2, key=k2),
            WifiObservation(lat=2.07, lon=2, key=k2),
            # a wifi with a very different prior position
            Wifi(lat=1.0, lon=1.0, key=k3, total_measures=1),
            WifiObservation(lat=3.0, lon=3.0, key=k3),
            WifiObservation(lat=-3.0, lon=3.0, key=k3),
            # another wifi with a prior known position (and negative lat)
            Wifi(lat=-4.0, lon=4.0, key=k4, total_measures=1),
            WifiObservation(lat=-4.1, lon=4, key=k4),
            WifiObservation(lat=-4.16, lon=4, key=k4),
            # an already blacklisted wifi
            WifiBlacklist(key=k5, time=now, count=1),
            WifiObservation(lat=5.0, lon=5.0, key=k5),
            WifiObservation(lat=5.1, lon=5.0, key=k5),
        ]
        observations = []
        for obj in data:
            if isinstance(obj, WifiObservation):
                observations.append(obj)
            else:
                self.session.add(obj)
        self.data_queue.enqueue(observations)
        self.session.commit()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (4, 3))

        black = self.session.query(WifiBlacklist).all()
        self.assertEqual(set([b.key for b in black]), set([k2, k3, k4, k5]))

        # test duplicate call
        result = update_wifi.delay()
        self.assertEqual(result.get(), (0, 0))

        self.check_stats(
            timer=[
                # We made duplicate calls
                ('task.data.update_wifi', 2),
                # One of those would've scheduled a remove_wifi task
                ('task.data.remove_wifi', 1)
            ])
예제 #10
0
    def _queue_and_update(self, obs):
        sharded_obs = defaultdict(list)
        for ob in obs:
            sharded_obs[WifiShard.shard_id(ob.mac)].append(ob)

        for shard_id, values in sharded_obs.items():
            queue = self.celery_app.data_queues['update_wifi_' + shard_id]
            queue.enqueue(values)
            update_wifi.delay(shard_id=shard_id).get()
예제 #11
0
    def test_stats(self):
        self.add_reports(3, api_key='test')
        schedule_export_reports.delay().get()
        update_cell.delay().get()
        update_wifi.delay().get()

        self.check_stats(
            counter=[('items.api_log.test.uploaded.reports', 1, 3),
                     ('items.uploaded.reports', 1, 3)])
예제 #12
0
    def _queue_and_update(self, obs):
        sharded_obs = defaultdict(list)
        for ob in obs:
            sharded_obs[WifiShard.shard_id(ob.mac)].append(ob)

        for shard_id, values in sharded_obs.items():
            queue = self.celery_app.data_queues['update_wifi_' + shard_id]
            queue.enqueue(values)
            update_wifi.delay(shard_id=shard_id).get()
예제 #13
0
 def test_wifi_invalid(self):
     self.add_reports(cell_factor=0, wifi_factor=1, wifi_key='abcd')
     schedule_export_reports.delay().get()
     update_wifi.delay().get()
     self.check_stats(counter=[
         ('data.report.upload', 1, 1, ['key:test']),
         ('data.report.drop', 1, 1, ['reason:malformed', 'key:test']),
         ('data.observation.drop', 1, 1,
             ['type:wifi', 'reason:malformed', 'key:test']),
     ])
예제 #14
0
    def _update_all(self):
        update_incoming.delay().get()

        for shard_id in BlueShard.shards().keys():
            update_blue.delay(shard_id=shard_id).get()

        for shard_id in CellShard.shards().keys():
            update_cell.delay(shard_id=shard_id).get()

        for shard_id in WifiShard.shards().keys():
            update_wifi.delay(shard_id=shard_id).get()
예제 #15
0
    def test_upload_wifi(self):
        reports = self.add_reports(cell_factor=0, wifi_factor=1)
        schedule_export_reports.delay().get()
        update_wifi.delay().get()

        position = reports[0]['position']
        wifi_data = reports[0]['wifiAccessPoints'][0]
        wifis = self.session.query(Wifi).all()
        self.assertEqual(len(wifis), 1)
        wifi = wifis[0]
        self.assertEqual(wifi.lat, position['latitude'])
        self.assertEqual(wifi.lon, position['longitude'])
        self.assertEqual(wifi.key, wifi_data['macAddress'])
        self.assertEqual(wifi.total_measures, 1)
예제 #16
0
    def _update_all(self, session, datamap_only=False):
        ExportConfigFactory(name="internal", batch=0, schema="internal")
        session.flush()
        update_incoming.delay().get()

        if datamap_only:
            return

        for shard_id in BlueShard.shards().keys():
            update_blue.delay(shard_id=shard_id).get()

        for shard_id in CellShard.shards().keys():
            update_cell.delay(shard_id=shard_id).get()

        for shard_id in WifiShard.shards().keys():
            update_wifi.delay(shard_id=shard_id).get()
예제 #17
0
    def _update_all(self, session, datamap_only=False):
        ExportConfigFactory(name='internal', batch=0, schema='internal')
        session.flush()
        update_incoming.delay().get()

        if datamap_only:
            return

        for shard_id in BlueShard.shards().keys():
            update_blue.delay(shard_id=shard_id).get()

        for shard_id in CellShard.shards().keys():
            update_cell.delay(shard_id=shard_id).get()

        for shard_id in WifiShard.shards().keys():
            update_wifi.delay(shard_id=shard_id).get()
예제 #18
0
    def test_max_min_range_update(self):
        wifi = WifiFactory(range=100, total_measures=4)
        wifi_lat = wifi.lat
        wifi_lon = wifi.lon
        wifi.max_lat = wifi.lat + 0.001
        wifi.min_lat = wifi.lat - 0.001
        wifi.max_lon = wifi.lon + 0.001
        wifi.min_lon = wifi.lon - 0.001

        observations = [
            WifiObservation(lat=wifi.lat + 0.002, lon=wifi.lon - 0.004,
                            key=wifi.key),
            WifiObservation(lat=wifi.lat - 0.002, lon=wifi.lon + 0.01,
                            key=wifi.key),
        ]
        self.data_queue.enqueue(observations)
        self.session.commit()

        self.assertEqual(update_wifi.delay().get(), (1, 0))

        wifis = self.session.query(Wifi).all()
        self.assertEqual(len(wifis), 1)
        wifi = wifis[0]

        self.assertAlmostEqual(wifi.lat, wifi_lat)
        self.assertAlmostEqual(wifi.max_lat, wifi_lat + 0.002)
        self.assertAlmostEqual(wifi.min_lat, wifi_lat - 0.002)
        self.assertAlmostEqual(wifi.lon, wifi_lon + 0.001)
        self.assertAlmostEqual(wifi.max_lon, wifi_lon + 0.01)
        self.assertAlmostEqual(wifi.min_lon, wifi_lon - 0.004)
        self.assertEqual(wifi.range, 662)
        self.assertEqual(wifi.total_measures, 6)
예제 #19
0
    def test_wifi(self):
        reports = self.add_reports(cell_factor=0, wifi_factor=1)
        schedule_export_reports.delay().get()
        update_wifi.delay().get()

        position = reports[0]['position']
        wifi_data = reports[0]['wifiAccessPoints'][0]
        mac = wifi_data['macAddress']
        shard = WifiShard.shard_model(mac)
        wifis = self.session.query(shard).all()
        self.assertEqual(len(wifis), 1)
        wifi = wifis[0]
        self.assertEqual(wifi.lat, position['latitude'])
        self.assertEqual(wifi.lon, position['longitude'])
        self.assertEqual(wifi.mac, wifi_data['macAddress'])
        self.assertEqual(wifi.samples, 1)
예제 #20
0
    def test_upload_duplicated_wifi(self):
        self.add_reports(cell_factor=0, wifi_factor=1)
        # duplicate the wifi entry inside the report
        queue = self.celery_app.export_queues['internal']
        items = queue.dequeue(queue.queue_key())
        report = items[0]['report']
        wifi = report['wifiAccessPoints'][0].copy()
        report['wifiAccessPoints'].append(wifi)
        report['wifiAccessPoints'][1]['signalStrength'] += 2
        queue.enqueue(items, queue.queue_key())

        schedule_export_reports.delay().get()
        update_wifi.delay().get()

        wifis = self.session.query(Wifi).all()
        self.assertEqual(len(wifis), 1)
        self.assertEqual(wifis[0].total_measures, 1)
예제 #21
0
    def test_insert_observations(self):
        session = self.session
        time = util.utcnow() - timedelta(days=1)

        wifi = WifiFactory(total_measures=0)
        wifi2 = WifiFactory.build(total_measures=0)
        user = User(nickname=u'test')
        session.add(user)
        session.flush()

        obs = dict(
            created=time, time=time, lat=wifi.lat, lon=wifi.lon,
            accuracy=None, altitude=None, altitude_accuracy=None,
            heading=52.9, speed=158.5,
        )
        entries = [
            {'key': wifi.key, 'channel': 11, 'signal': -80},
            {'key': wifi.key, 'channel': 3, 'signal': -90},
            {'key': wifi.key, 'channel': 3, 'signal': -80},
            {'key': wifi2.key, 'channel': 3, 'signal': -90},
        ]
        for entry in entries:
            entry.update(obs)
        result = insert_measures_wifi.delay(entries, userid=user.id)
        self.assertEqual(result.get(), 4)

        self.assertEqual(self.data_queue.size(), 4)
        update_wifi.delay().get()

        self.session.refresh(wifi)
        wifis = session.query(Wifi).all()
        self.assertEqual(len(wifis), 2)
        self._compare_sets([w.key for w in wifis], [wifi.key, wifi2.key])
        self._compare_sets([w.total_measures for w in wifis], [1, 3])

        score_queue = self.celery_app.data_queues['update_score']
        scores = score_queue.dequeue()
        self.assertEqual(len(scores), 1)
        score = scores[0]
        self.assertEqual(score['hashkey'].userid, user.id)
        self.assertEqual(score['hashkey'].key, ScoreKey.new_wifi)
        self.assertEqual(score['value'], 1)

        self.check_statcounter(StatKey.wifi, 4)
        self.check_statcounter(StatKey.unique_wifi, 1)
예제 #22
0
    def test_max_min_range_update(self):
        k1 = 'ab1234567890'
        k2 = 'cd1234567890'
        data = [
            Wifi(key=k1, total_measures=2),
            WifiObservation(lat=1.0, lon=1.0, key=k1),
            WifiObservation(lat=1.002, lon=1.004, key=k1),
            Wifi(key=k2, lat=2.0, lon=-2.0,
                 max_lat=2.001, min_lat=1.999,
                 max_lon=-1.999, min_lon=-2.001,
                 total_measures=4),
            WifiObservation(lat=2.002, lon=-2.004, key=k2),
            WifiObservation(lat=1.998, lon=-1.996, key=k2),
        ]
        observations = []
        for obj in data:
            if isinstance(obj, WifiObservation):
                observations.append(obj)
            else:
                self.session.add(obj)
        self.data_queue.enqueue(observations)
        self.session.commit()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (2, 0))

        wifis = dict(self.session.query(Wifi.key, Wifi).all())
        self.assertEqual(set(wifis.keys()), set([k1, k2]))

        self.assertEqual(wifis[k1].lat, 1.001)
        self.assertEqual(wifis[k1].max_lat, 1.002)
        self.assertEqual(wifis[k1].min_lat, 1.0)
        self.assertEqual(wifis[k1].lon, 1.002)
        self.assertEqual(wifis[k1].max_lon, 1.004)
        self.assertEqual(wifis[k1].min_lon, 1.0)

        self.assertEqual(wifis[k2].lat, 2.0)
        self.assertEqual(wifis[k2].max_lat, 2.002)
        self.assertEqual(wifis[k2].min_lat, 1.998)
        self.assertEqual(wifis[k2].lon, -2.0)
        self.assertEqual(wifis[k2].max_lon, -1.996)
        self.assertEqual(wifis[k2].min_lon, -2.004)

        # independent calculation: the k1 bounding box is
        # (1.000, 1.000) to (1.002, 1.004), with centroid
        # at (1.001, 1.002); worst distance from centroid
        # to any corner is 249m
        self.assertEqual(wifis[k1].range, 249)

        # independent calculation: the k2 bounding box is
        # (1.998, -2.004) to (2.002, -1.996), with centroid
        # at (2.000, 2.000); worst distance from centroid
        # to any corner is 497m
        self.assertEqual(wifis[k2].range, 497)
예제 #23
0
    def test_wifi_duplicated(self):
        self.add_reports(cell_factor=0, wifi_factor=1)
        # duplicate the wifi entry inside the report
        queue = self.celery_app.export_queues['internal']
        items = queue.dequeue(queue.queue_key())
        report = items[0]['report']
        wifi = report['wifiAccessPoints'][0]
        mac = wifi['macAddress']
        report['wifiAccessPoints'].append(wifi.copy())
        report['wifiAccessPoints'].append(wifi.copy())
        report['wifiAccessPoints'][1]['signalStrength'] += 2
        report['wifiAccessPoints'][2]['signalStrength'] -= 2
        queue.enqueue(items, queue.queue_key())

        schedule_export_reports.delay().get()
        update_wifi.delay().get()

        shard = WifiShard.shard_model(mac)
        wifis = self.session.query(shard).all()
        self.assertEqual(len(wifis), 1)
        self.assertEqual(wifis[0].samples, 1)
예제 #24
0
    def test_blacklist_time_used_as_creation_time(self):
        now = util.utcnow()
        last_week = now - TEMPORARY_BLACKLIST_DURATION - timedelta(days=1)

        wifi = WifiFactory.build()
        self.session.add(WifiBlacklist(time=last_week, count=1, key=wifi.key))
        self.session.flush()

        # add a new entry for the previously blacklisted wifi
        obs = dict(lat=wifi.lat, lon=wifi.lon, key=wifi.key)
        insert_measures_wifi.delay([obs]).get()

        self.assertEqual(self.data_queue.size(), 1)
        update_wifi.delay().get()

        # the wifi was inserted again
        wifis = self.session.query(Wifi).all()
        self.assertEqual(len(wifis), 1)

        # and the creation date was set to the date of the blacklist entry
        self.assertEqual(wifis[0].created, last_week)
        self.check_statcounter(StatKey.unique_wifi, 0)
예제 #25
0
    def test_upload(self):
        self.session.add(ApiKey(valid_key='e5444-794', log=True))
        self.session.flush()

        self.add_reports(3, email='secretemail@localhost',
                         ip=self.geoip_data['London']['ip'])
        self.add_reports(6, api_key='e5444-794')
        self.add_reports(3, api_key=None)

        schedule_export_reports.delay().get()
        update_cell.delay().get()
        update_wifi.delay().get()

        self.assertEqual(self.session.query(Cell).count(), 12)
        self.assertEqual(self.session.query(Wifi).count(), 24)

        self.check_stats(counter=[
            ('items.export.internal.batches', 1, 1),
            ('items.api_log.test.uploaded.cell_observations', 1, 3),
            ('items.api_log.test.uploaded.wifi_observations', 1, 6),
            ('items.api_log.no_key.uploaded.cell_observations', 0),
            ('items.api_log.e5444-794.uploaded.cell_observations', 1, 6),
            ('items.api_log.e5444-794.uploaded.wifi_observations', 1, 12),
        ])
예제 #26
0
    def test_temp_blocked(self):
        utcnow = util.utcnow()
        bad_wifi = WifiObservationFactory.build()
        good_wifi = WifiObservationFactory.build()
        WifiShardFactory(
            mac=bad_wifi.mac,
            lat=None,
            lon=None,
            created=utcnow,
            block_first=utcnow.date() - timedelta(days=10),
            block_last=utcnow.date(),
            block_count=1)
        self.session.flush()

        observations = [good_wifi, bad_wifi, good_wifi]
        self.data_queue.enqueue(observations)
        self.assertEqual(self.data_queue.size(), 3)
        update_wifi.delay().get()

        shard = WifiShard.shard_model(good_wifi.mac)
        wifis = (self.session.query(shard)
                             .filter(shard.mac == good_wifi.mac)).all()
        self.assertEqual(len(wifis), 1)
        self.assertTrue(wifis[0].lat is not None)
        self.assertTrue(wifis[0].lon is not None)
        self.assertEqual(wifis[0].samples, 2)

        shard = WifiShard.shard_model(bad_wifi.mac)
        wifis = (self.session.query(shard)
                             .filter(shard.mac == bad_wifi.mac)).all()
        self.assertEqual(len(wifis), 1)
        self.assertTrue(wifis[0].lat is None)
        self.assertTrue(wifis[0].lon is None)

        self.check_statcounter(StatKey.wifi, 2)
        self.check_statcounter(StatKey.unique_wifi, 1)
예제 #27
0
    def test_update_wifi(self):
        wifis = WifiFactory.create_batch(2)
        obs = []
        obs_factory = WifiObservationFactory
        # first wifi
        wifi = wifis[0]
        wifi.total_measures = 3
        lat1, lon1 = (wifi.lat, wifi.lon)
        obs.extend([
            obs_factory(lat=wifi.lat,
                        lon=wifi.lon, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.002,
                        lon=wifi.lon + 0.003, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.004,
                        lon=wifi.lon + 0.006, key=wifi.key),
        ])
        wifi.lat = None
        wifi.lon = None
        # second wifi
        wifi = wifis[1]
        wifi.total_measures = 2
        wifi.lat += 1.0
        wifi.lon += 1.0
        lat2, lon2 = (wifi.lat, wifi.lon)
        obs.extend([
            obs_factory(lat=wifi.lat + 0.002,
                        lon=wifi.lon + 0.004, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.002,
                        lon=wifi.lon + 0.004, key=wifi.key),
        ])
        self.data_queue.enqueue(obs)
        self.session.commit()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (2, 0))
        self.check_stats(
            timer=['task.data.update_wifi'],
        )

        found = dict(self.session.query(Wifi.key, Wifi).all())
        self.assertEqual(set(found.keys()), set([wifis[0].key, wifis[1].key]))
        self.assertAlmostEqual(found[wifis[0].key].lat, lat1 + 0.002)
        self.assertAlmostEqual(found[wifis[0].key].lon, lon1 + 0.003)
        self.assertAlmostEqual(found[wifis[1].key].lat, lat2 + 0.001)
        self.assertAlmostEqual(found[wifis[1].key].lon, lon2 + 0.002)
예제 #28
0
    def test_update_wifi(self):
        obs = []
        obs_factory = WifiObservationFactory
        # first wifi
        wifi1 = WifiFactory(lat=None, lon=None, total_measures=3)
        new_pos = WifiFactory.build()
        lat1, lon1 = (new_pos.lat, new_pos.lon)
        obs.extend([
            obs_factory(lat=lat1,
                        lon=lon1, key=wifi1.key),
            obs_factory(lat=lat1 + 0.002,
                        lon=lon1 + 0.003, key=wifi1.key),
            obs_factory(lat=lat1 + 0.004,
                        lon=lon1 + 0.006, key=wifi1.key),
        ])
        # second wifi
        wifi2 = WifiFactory(lat=lat1 + 1.0, lon=lon1 + 1.0, total_measures=2)
        lat2, lon2 = (wifi2.lat, wifi2.lon)
        obs.extend([
            obs_factory(lat=lat2 + 0.002,
                        lon=lon2 + 0.004, key=wifi2.key),
            obs_factory(lat=lat2 + 0.002,
                        lon=lon2 + 0.004, key=wifi2.key),
        ])
        self.data_queue.enqueue(obs)
        self.session.flush()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (2, 0))
        self.check_stats(
            timer=['task.data.update_wifi'],
        )
        self.session.refresh(wifi1)
        self.session.refresh(wifi2)

        found = dict(self.session.query(Wifi.key, Wifi).all())
        self.assertEqual(set(found.keys()), set([wifi1.key, wifi2.key]))
        self.assertAlmostEqual(found[wifi1.key].lat, lat1 + 0.002)
        self.assertAlmostEqual(found[wifi1.key].lon, lon1 + 0.003)
        self.assertAlmostEqual(found[wifi2.key].lat, lat2 + 0.001)
        self.assertAlmostEqual(found[wifi2.key].lon, lon2 + 0.002)
예제 #29
0
    def test_update_wifi(self):
        now = util.utcnow()
        k1 = 'ab1234567890'
        k2 = 'cd1234567890'
        data = [
            Wifi(key=k1, total_measures=3),
            WifiObservation(lat=1.0, lon=1.0, key=k1, created=now),
            WifiObservation(lat=1.002, lon=1.003, key=k1, created=now),
            WifiObservation(lat=1.004, lon=1.006, key=k1, created=now),
            Wifi(key=k2, lat=2.0, lon=2.0, total_measures=2),
            WifiObservation(lat=2.002, lon=2.004, key=k2, created=now),
            WifiObservation(lat=2.002, lon=2.004, key=k2, created=now),
        ]
        observations = []
        for obj in data:
            if isinstance(obj, WifiObservation):
                observations.append(obj)
            else:
                self.session.add(obj)
        self.data_queue.enqueue(observations)
        self.session.commit()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (2, 0))
        self.check_stats(
            timer=['task.data.update_wifi'],
        )

        wifis = dict(self.session.query(Wifi.key, Wifi).all())
        self.assertEqual(set(wifis.keys()), set([k1, k2]))

        self.assertEqual(wifis[k1].lat, 1.002)
        self.assertEqual(wifis[k1].lon, 1.003)

        self.assertEqual(wifis[k2].lat, 2.001)
        self.assertEqual(wifis[k2].lon, 2.002)
예제 #30
0
    def test_blacklist_moving_wifis(self):
        now = util.utcnow()
        obs = []
        obs_factory = WifiObservationFactory
        moving = set()
        wifis = WifiFactory.create_batch(4)
        wifis.append(WifiFactory.build())
        # a wifi with an entry but no prior position
        wifi = wifis[0]
        wifi.total_measures = 0
        obs.extend([
            obs_factory(lat=wifi.lat + 0.001,
                        lon=wifi.lon + 0.001, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.002,
                        lon=wifi.lon + 0.005, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.003,
                        lon=wifi.lon + 0.009, key=wifi.key),
        ])
        wifi.lat = None
        wifi.lon = None
        # a wifi with a prior known position
        wifi = wifis[1]
        wifi.total_measures = 1
        wifi.lat += 1.0
        wifi.lon += 1.0
        obs.extend([
            obs_factory(lat=wifi.lat + 0.01,
                        lon=wifi.lon, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.07,
                        lon=wifi.lon, key=wifi.key),
        ])
        moving.add(wifi.hashkey())
        # a wifi with a very different prior position
        wifi = wifis[2]
        wifi.total_measures = 1
        obs.extend([
            obs_factory(lat=wifi.lat + 2.0,
                        lon=wifi.lon + 2.0, key=wifi.key),
            obs_factory(lat=wifi.lat - 4.0,
                        lon=wifi.lon + 2.0, key=wifi.key),
        ])
        moving.add(wifi.hashkey())
        # another wifi with a prior known position (and negative lat)
        wifi = wifis[3]
        wifi.total_measures = 1
        wifi.lat *= -1.0
        obs.extend([
            obs_factory(lat=wifi.lat - 0.1,
                        lon=wifi.lon, key=wifi.key),
            obs_factory(lat=wifi.lat - 0.16,
                        lon=wifi.lon, key=wifi.key),
        ])
        moving.add(wifi.hashkey())
        # an already blacklisted wifi
        wifi = wifis[4]
        WifiBlacklistFactory(key=wifi.key, time=now, count=1)
        obs.extend([
            obs_factory(lat=wifi.lat,
                        lon=wifi.lon, key=wifi.key),
            obs_factory(lat=wifi.lat + 0.1,
                        lon=wifi.lon, key=wifi.key),
        ])
        moving.add(wifi.hashkey())

        self.data_queue.enqueue(obs)
        self.session.commit()

        result = update_wifi.delay()
        self.assertEqual(result.get(), (4, 3))

        black = self.session.query(WifiBlacklist).all()
        self.assertEqual(set([b.hashkey() for b in black]), moving)

        # test duplicate call
        result = update_wifi.delay()
        self.assertEqual(result.get(), (0, 0))

        self.check_stats(
            timer=[
                # We made duplicate calls
                ('task.data.update_wifi', 2),
                # One of those would've scheduled a remove_wifi task
                ('task.data.remove_wifi', 1)
            ])
예제 #31
0
 def test_upload_invalid_wifi(self):
     self.add_reports(cell_factor=0, wifi_factor=1, wifi_key='abcd')
     schedule_export_reports.delay().get()
     update_wifi.delay().get()
     self.assertEqual(self.session.query(Wifi).count(), 0)
예제 #32
0
    def test_blacklist_temporary_and_permanent(self):
        # This test simulates a wifi that moves once a month, for 2 years.
        # The first 2 * PERMANENT_BLACKLIST_THRESHOLD (12) moves should be
        # temporary, forgotten after a week; after that it should be
        # permanently blacklisted.

        now = util.utcnow()
        # Station moves between these 4 points, all in the USA:
        points = [
            # NYC
            (40.0, -74.0),
            # SF
            (37.0, -122.0),
            # Seattle
            (47.0, -122.0),
            # Miami
            (25.0, -80.0),
        ]

        N = 4 * PERMANENT_BLACKLIST_THRESHOLD
        for month in range(0, N):
            days_ago = (N - (month + 1)) * 30
            time = now - timedelta(days=days_ago)

            obs = dict(key='ab1234567890',
                       time=time,
                       lat=points[month % 4][0],
                       lon=points[month % 4][1])

            # insert_result is num-accepted-observations, override
            # utcnow to set creation date
            insert_result = insert_measures_wifi.delay(
                [obs], utcnow=time)

            # update_result is (num-stations, num-moving-stations)
            update_result = update_wifi.delay()

            # Assuming PERMANENT_BLACKLIST_THRESHOLD == 6:
            #
            # 0th insert will create the station
            # 1st insert will create first blacklist entry, delete station
            # 2nd insert will recreate the station at new position
            # 3rd insert will update blacklist, re-delete station
            # 4th insert will recreate the station at new position
            # 5th insert will update blacklist, re-delete station
            # 6th insert will recreate the station at new position
            # ...
            # 11th insert will make blacklisting permanent, re-delete station
            # 12th insert will not recreate station
            # 13th insert will not recreate station
            # ...
            # 23rd insert will not recreate station

            bl = self.session.query(WifiBlacklist).all()
            if month == 0:
                self.assertEqual(len(bl), 0)
            else:
                self.assertEqual(len(bl), 1)
                # force the blacklist back in time to whenever the
                # observation was supposedly inserted.
                bl = bl[0]
                bl.time = time
                self.session.add(bl)
                self.session.commit()

            if month < N / 2:
                # We still haven't exceeded the threshold, so the
                # observation was admitted.
                self.assertEqual(insert_result.get(), 1)
                if month % 2 == 0:
                    # The station was (re)created.
                    self.assertEqual(update_result.get(), (1, 0))
                    # One wifi record should exist.
                    self.assertEqual(self.session.query(Wifi).count(), 1)
                else:
                    # The station existed and was seen moving,
                    # thereby activating the blacklist.
                    self.assertEqual(update_result.get(), (1, 1))
                    self.assertEqual(bl.count, ((month + 1) / 2))
                    self.assertEqual(
                        self.session.query(WifiBlacklist).count(), 1)
                    self.assertEqual(self.session.query(Wifi).count(), 0)

                    # Try adding one more observation 1 day later
                    # to be sure it is dropped by the now-active blacklist.
                    next_day = time + timedelta(days=1)
                    obs['time'] = next_day
                    self.assertEqual(
                        0, insert_measures_wifi.delay([obs],
                                                      utcnow=next_day).get())

            else:
                # Blacklist has exceeded threshold, gone to permanent mode,
                # so no observation accepted, no stations seen.
                self.assertEqual(insert_result.get(), 0)
                self.assertEqual(update_result.get(), (0, 0))
예제 #33
0
    def test_blocklist_moving_wifis(self):
        now = util.utcnow()
        obs = []
        obs_factory = WifiObservationFactory
        moving = set()
        wifis = WifiShardFactory.create_batch(8)
        wifis.append(WifiShardFactory.build())
        # a wifi without an entry and disagreeing observations
        wifi = wifis[-1]
        obs.extend([
            obs_factory(lat=wifi.lat, lon=wifi.lon, key=wifi.mac),
            obs_factory(lat=wifi.lat + 2.0, lon=wifi.lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # a wifi with an entry but no prior position
        wifi = wifis[0]
        obs.extend([
            obs_factory(lat=wifi.lat + 0.001,
                        lon=wifi.lon + 0.001, key=wifi.mac),
            obs_factory(lat=wifi.lat + 0.002,
                        lon=wifi.lon + 0.005, key=wifi.mac),
            obs_factory(lat=wifi.lat + 0.003,
                        lon=wifi.lon + 0.009, key=wifi.mac),
        ])
        wifi.lat = None
        wifi.lon = None
        wifi.samples = 0
        # a wifi with a prior known position
        wifi = wifis[1]
        wifi.samples = 1
        wifi.lat += 1.0
        wifi.lon += 1.0
        obs.extend([
            obs_factory(lat=wifi.lat + 0.01,
                        lon=wifi.lon, key=wifi.mac),
            obs_factory(lat=wifi.lat + 0.07,
                        lon=wifi.lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # a wifi with a very different prior position
        wifi = wifis[2]
        wifi.samples = 1
        obs.extend([
            obs_factory(lat=wifi.lat + 2.0,
                        lon=wifi.lon, key=wifi.mac),
            obs_factory(lat=wifi.lat + 2.002,
                        lon=wifi.lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # another wifi with a prior known position (and negative lat)
        wifi = wifis[3]
        wifi.samples = 1
        wifi.lat *= -1.0
        obs.extend([
            obs_factory(lat=wifi.lat - 0.1,
                        lon=wifi.lon, key=wifi.mac),
            obs_factory(lat=wifi.lat - 0.16,
                        lon=wifi.lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # an already blocked wifi
        wifi = wifis[4]
        wifi.block_last = now.date()
        wifi.block_count = 1
        obs.extend([
            obs_factory(lat=wifi.lat,
                        lon=wifi.lon, key=wifi.mac),
            obs_factory(lat=wifi.lat + 0.1,
                        lon=wifi.lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # a permanently blocked wifi
        wifi = wifis[5]
        wifi_lat, wifi_lon = (wifi.lat, wifi.lon)
        wifi.block_last = now.date() - 2 * TEMPORARY_BLOCKLIST_DURATION
        wifi.block_count = PERMANENT_BLOCKLIST_THRESHOLD
        for col in ('lat', 'lon', 'max_lat', 'min_lat', 'max_lon', 'min_lon'):
            setattr(wifi, col, None)
        obs.extend([
            obs_factory(lat=wifi_lat, lon=wifi_lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)
        # a no longer blocked wifi
        wifi = wifis[6]
        wifi_lat, wifi_lon = (wifi.lat, wifi.lon)
        wifi.block_last = now.date() - 2 * TEMPORARY_BLOCKLIST_DURATION
        wifi.block_count = 2
        for col in ('lat', 'lon', 'max_lat', 'min_lat', 'max_lon', 'min_lon'):
            setattr(wifi, col, None)
        obs.extend([
            obs_factory(lat=wifi_lat, lon=wifi_lon, key=wifi.mac),
        ])
        # a no longer blocked wifi with disagreeing observations
        wifi = wifis[7]
        wifi_lat, wifi_lon = (wifi.lat, wifi.lon)
        wifi.block_last = now.date() - 2 * TEMPORARY_BLOCKLIST_DURATION
        wifi.block_count = 2
        for col in ('lat', 'lon', 'max_lat', 'min_lat', 'max_lon', 'min_lon'):
            setattr(wifi, col, None)
        obs.extend([
            obs_factory(lat=wifi_lat, lon=wifi_lon, key=wifi.mac),
            obs_factory(lat=wifi_lat + 2.0, lon=wifi_lon, key=wifi.mac),
        ])
        moving.add(wifi.mac)

        self.data_queue.enqueue(obs)
        self.session.commit()
        update_wifi.delay().get()

        shards = set()
        for mac in moving:
            shards.add(WifiShard.shard_model(mac))
        blocks = []
        for shard in shards:
            for row in self.session.query(shard).all():
                if row.blocked():
                    blocks.append(row)
        self.assertEqual(set([b.mac for b in blocks]), moving)

        self.check_stats(counter=[
            ('data.observation.drop', 1, 3,
                ['type:wifi', 'reason:blocklisted']),
            ('data.station.blocklist', 1, 5,
                ['type:wifi', 'action:add', 'reason:moving']),
        ])
예제 #34
0
    def test_update(self):
        utcnow = util.utcnow()
        obs = []
        obs_factory = WifiObservationFactory
        # first wifi
        wifi1 = WifiShardFactory(lat=None, lon=None, samples=3)
        new_pos = WifiShardFactory.build()
        mac1, lat1, lon1 = (wifi1.mac, new_pos.lat, new_pos.lon)
        obs.extend([
            obs_factory(lat=lat1,
                        lon=lon1, key=mac1),
            obs_factory(lat=lat1 + 0.002,
                        lon=lon1 + 0.003, key=mac1),
            obs_factory(lat=lat1 + 0.004,
                        lon=lon1 + 0.006, key=mac1),
        ])
        # second wifi
        wifi2 = WifiShardFactory(
            lat=lat1 + 1.0, lon=lon1 + 1.0,
            max_lat=lat1 + 1.0, min_lat=lat1 + 0.999,
            max_lon=lon1 + 1.0, min_lon=None,
            radius=20, samples=2,
            created=utcnow - timedelta(10),
            modified=utcnow - timedelta(10))
        mac2, lat2, lon2 = (wifi2.mac, wifi2.lat, wifi2.lon)
        obs.extend([
            obs_factory(lat=lat2 + 0.002,
                        lon=lon2 + 0.004, key=mac2),
            obs_factory(lat=lat2 + 0.002,
                        lon=lon2 + 0.004, key=mac2),
        ])
        self.data_queue.enqueue(obs)
        self.session.commit()
        update_wifi.delay().get()

        shard = WifiShard.shard_model(mac1)
        found = self.session.query(shard).filter(shard.mac == mac1).one()
        self.assertAlmostEqual(found.lat, lat1 + 0.002)
        self.assertAlmostEqual(found.max_lat, lat1 + 0.004)
        self.assertAlmostEqual(found.min_lat, lat1)
        self.assertAlmostEqual(found.lon, lon1 + 0.003)
        self.assertAlmostEqual(found.max_lon, lon1 + 0.006)
        self.assertAlmostEqual(found.min_lon, lon1)
        self.assertEqual(found.modified.date(), utcnow.date())
        self.assertEqual(found.country, 'GB')
        self.assertEqual(found.radius, 304)
        self.assertEqual(found.samples, 6)

        shard = WifiShard.shard_model(mac2)
        found = self.session.query(shard).filter(shard.mac == mac2).one()
        self.assertAlmostEqual(found.lat, lat2 + 0.001)
        self.assertAlmostEqual(found.max_lat, lat2 + 0.002)
        self.assertAlmostEqual(found.min_lat, lat2 - 0.001)
        self.assertAlmostEqual(found.lon, lon2 + 0.002)
        self.assertAlmostEqual(found.max_lon, lon2 + 0.004)
        self.assertAlmostEqual(found.min_lon, lon2)
        self.assertEqual(found.created.date(), utcnow.date() - timedelta(10))
        self.assertEqual(found.modified.date(), utcnow.date())
        self.assertEqual(found.country, 'GB')
        self.assertEqual(found.radius, 260)
        self.assertEqual(found.samples, 4)