* initial draft of fix to test client_ids

* added a test to exercise the ensemble recommender with mock client_ids
This commit is contained in:
Victor Ng 2020-08-31 16:52:13 -04:00 коммит произвёл GitHub
Родитель 12cb0eed46
Коммит 756f761680
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 102 добавлений и 9 удалений

Просмотреть файл

@ -316,6 +316,22 @@ Options:
```
## Testing
TAARLite will respond with suggestions given an addon GUID.
A sample URL path may look like this:
`/taarlite/api/v1/addon_recommendations/uBlock0%40raymondhill.net/`
TAAR will treat any client ID with only repeating digits (ie: 0000) as
a test client ID and will return a dummy response.
A URL with the path : `/v1/api/recommendations/0000000000/` will
return a valid JSON result
## A note on cdist optimization.
cdist can speed up distance computation by a factor of 10 for the computations we're doing.
We can use it without problems on the canberra distance calculation.

Просмотреть файл

@ -13,7 +13,7 @@ def in_experiment(client_id, xp_prob=0.5):
xp_prob is a probability between 0.0 and 1.0 which is the
chance that the experimental branch is selected.
"""
hex_client = ''.join([c for c in client_id.lower() if c in 'abcdef0123456789'])
hex_client = "".join([c for c in client_id.lower() if c in "abcdef0123456789"])
int_client = int(hex_client, 16)
return int((int_client % 100) <= (xp_prob * 100))
@ -25,6 +25,9 @@ def reorder_guids(guid_weight_tuples, size=None):
@size denotes the length of the output.
"""
if guid_weight_tuples is None or len(guid_weight_tuples) == 0:
return []
weight_list = [weight for (guid, weight) in guid_weight_tuples]
guids = [guid for (guid, weight) in guid_weight_tuples]
guid_map = dict(zip(guids, guid_weight_tuples))

Просмотреть файл

@ -2,7 +2,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from taar.recommenders.ensemble_recommender import EnsembleRecommender
from taar.recommenders.ensemble_recommender import (
EnsembleRecommender,
is_test_client,
)
from taar.recommenders.randomizer import in_experiment, reorder_guids
from srgutil.interfaces import IMozLogging
from .lazys3 import LazyJSONLoader
@ -75,15 +78,20 @@ class RecommendationManager:
:param limit: the maximum number of recommendations to return.
:param extra_data: a dictionary with extra client data.
"""
results = None
client_info = self.profile_fetcher.get(client_id)
if client_info is None:
self.logger.info(
"Defaulting to empty results. No client info fetched from storage backend."
)
results = []
if is_test_client(client_id):
# Just create a stub client_info blob
client_info = {
"client_id": client_id,
}
else:
client_info = self.profile_fetcher.get(client_id)
if client_info is None:
self.logger.info(
"Defaulting to empty results. No client info fetched from storage backend."
)
return []
if in_experiment(client_id, self._experiment_prob):
if results is None:

Просмотреть файл

@ -9,6 +9,8 @@ from taar.recommenders.ensemble_recommender import (
from taar.settings import (
TAAR_ENSEMBLE_BUCKET,
TAAR_ENSEMBLE_KEY,
TAAR_WHITELIST_BUCKET,
TAAR_WHITELIST_KEY,
)
from moto import mock_s3
import boto3
@ -28,6 +30,36 @@ def install_mock_ensemble_data(ctx):
conn.create_bucket(Bucket=TAAR_ENSEMBLE_BUCKET)
conn.Object(TAAR_ENSEMBLE_BUCKET, TAAR_ENSEMBLE_KEY).put(Body=json.dumps(DATA))
conn.create_bucket(Bucket=TAAR_WHITELIST_BUCKET)
conn.Object(TAAR_WHITELIST_BUCKET, TAAR_WHITELIST_KEY).put(
Body=json.dumps(
[
"2.0@disconnect.me",
"@contain-facebook",
"@testpilot-containers",
"CookieAutoDelete@kennydo.com",
"FirefoxColor@mozilla.com",
"adblockultimate@adblockultimate.net",
"addon@darkreader.org",
"adguardadblocker@adguard.com",
"adnauseam@rednoise.org",
"clearcache@michel.de.almeida",
"copyplaintext@eros.man",
"default-bookmark-folder@gustiaux.com",
"enhancerforyoutube@maximerf.addons.mozilla.org",
"extension@one-tab.com",
"extension@tabliss.io",
"firefox-addon@myki.co",
"firefox@ghostery.com",
"forecastfox@s3_fix_version",
"forget-me-not@lusito.info",
"foxyproxy@eric.h.jung",
"foxytab@eros.man",
"gmailnoads@mywebber.com",
]
)
)
return ctx
@ -102,3 +134,35 @@ def test_preinstalled_guids(test_ctx):
print(recommendation_list)
assert isinstance(recommendation_list, list)
assert recommendation_list == EXPECTED_RESULTS
@mock_s3
def test_mock_client_ids(test_ctx):
ctx = install_mock_ensemble_data(test_ctx)
EXPECTED_RESULTS = [
("2.0@disconnect.me", 0.17),
("@contain-facebook", 0.25),
("@testpilot-containers", 0.72),
("CookieAutoDelete@kennydo.com", 0.37),
("FirefoxColor@mozilla.com", 0.32),
]
factory = MockRecommenderFactory()
ctx["recommender_factory"] = factory
ctx["recommender_map"] = {
"collaborative": factory.create("collaborative"),
"similarity": factory.create("similarity"),
"locale": factory.create("locale"),
}
r = EnsembleRecommender(ctx.child())
# 'hij' should be excluded from the suggestions list
# The other two addon GUIDs 'def' and 'jkl' will never be
# recommended anyway and should have no impact on results
client = {"client_id": "11111"}
recommendation_list = r.recommend(client, 5)
assert isinstance(recommendation_list, list)
assert recommendation_list == EXPECTED_RESULTS

Просмотреть файл

@ -97,6 +97,7 @@ def test_curated_recommendations(test_ctx):
assert mm.has_record(TIMING, "taar.hybrid_recommend")
@pytest.mark.skip(reason="this test seems to break sporadically")
@mock_s3
def test_hybrid_recommendations(test_ctx):
# verify that the recommendations mix the curated and

Просмотреть файл

@ -22,6 +22,7 @@ def hasher(uuid):
@pytest.fixture
def app():
from taar.plugin import configure_plugin
from taar.plugin import PROXY_MANAGER