async def test_save_ut(users, redis_cache): owner_id = 1234 ut = user_tokens.UserTokens( redis_cache, owner_id, users, ) await ut.save_to_cache() rut = await user_tokens.UserTokens._retrieve_from_cache(redis_cache, owner_id) assert ut == rut
async def test_user_tokens_tokens_via_env(monkeypatch, redis_cache): ut = user_tokens.UserTokens(redis_cache, 123, {}) assert ut.get_token_for("foo") is None assert ut.get_token_for("login") is None assert ut.get_token_for("nop") is None monkeypatch.setattr(config, "ACCOUNT_TOKENS", config.AccountTokens("foo:bar,login:token")) assert ut.get_token_for("foo") == "bar" assert ut.get_token_for("login") == "token" assert ut.get_token_for("nop") is None
async def test_user_tokens_db_unavailable(retrieve_from_db_mock, redis_cache): owner_id = 1234 ut = user_tokens.UserTokens(redis_cache, owner_id, []) retrieve_from_db_mock.return_value = ut # no cache, no db -> reraise retrieve_from_db_mock.side_effect = http.HTTPServiceUnavailable( "boom!", response=mock.Mock(), request=mock.Mock() ) with pytest.raises(http.HTTPServiceUnavailable): await user_tokens.UserTokens.get(redis_cache, owner_id) retrieve_from_db_mock.assert_called_once() # no cache, but db -> got db ut retrieve_from_db_mock.reset_mock() retrieve_from_db_mock.side_effect = None rut = await user_tokens.UserTokens.get(redis_cache, owner_id) assert ut == rut retrieve_from_db_mock.assert_called_once() # cache not expired and not db -> got cached ut retrieve_from_db_mock.reset_mock() rut = await user_tokens.UserTokens.get(redis_cache, owner_id) ut.ttl = 259200 assert rut == ut retrieve_from_db_mock.assert_not_called() # cache expired and not db -> got cached ut retrieve_from_db_mock.reset_mock() retrieve_from_db_mock.side_effect = http.HTTPServiceUnavailable( "boom!", response=mock.Mock(), request=mock.Mock() ) await redis_cache.expire(f"user-tokens-cache-owner-{owner_id}", 7200) rut = await user_tokens.UserTokens.get(redis_cache, owner_id) ut.ttl = 7200 assert rut == ut retrieve_from_db_mock.assert_called_once() # cache expired and unexpected db issue -> reraise retrieve_from_db_mock.reset_mock() retrieve_from_db_mock.side_effect = Exception("WTF") await redis_cache.expire(f"user-tokens-cache-owner-{owner_id}", 7200) with pytest.raises(Exception): await user_tokens.UserTokens.get(redis_cache, owner_id) retrieve_from_db_mock.assert_called_once()
async def fake_user_tokens(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return await real_get_user_tokens(redis_cache, owner_id) return user_tokens.UserTokens(redis_cache, owner_id, {})
async def fake_retrieve_user_tokens_from_db(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return self.user_tokens return user_tokens.UserTokens(redis_cache, owner_id, {})
async def asyncSetUp(self): super(FunctionalTestBase, self).setUp() self.existing_labels: typing.List[str] = [] self.protected_branches: typing.Set[str] = set() self.pr_counter: int = 0 self.git_counter: int = 0 self.cassette_library_dir = os.path.join(CASSETTE_LIBRARY_DIR_BASE, self.__class__.__name__, self._testMethodName) # Recording stuffs if RECORD: if os.path.exists(self.cassette_library_dir): shutil.rmtree(self.cassette_library_dir) os.makedirs(self.cassette_library_dir) self.recorder = vcr.VCR( cassette_library_dir=self.cassette_library_dir, record_mode="all" if RECORD else "none", match_on=["method", "uri"], ignore_localhost=True, filter_headers=[ ("Authorization", "<TOKEN>"), ("X-Hub-Signature", "<SIGNATURE>"), ("User-Agent", None), ("Accept-Encoding", None), ("Connection", None), ], before_record_response=self.response_filter, ) if RECORD: github.CachedToken.STORAGE = {} else: # Never expire token during replay mock.patch.object(github_app, "get_or_create_jwt", return_value="<TOKEN>").start() mock.patch.object( github.GithubAppInstallationAuth, "get_access_token", return_value="<TOKEN>", ).start() # NOTE(sileht): httpx pyvcr stubs does not replay auth_flow as it directly patch client.send() # So anything occurring during auth_flow have to be mocked during replay def get_auth(owner_name=None, owner_id=None, auth=None): if auth is None: auth = github.get_auth(owner_name, owner_id) auth.installation = { "id": config.INSTALLATION_ID, } auth.permissions_need_to_be_updated = False auth.owner_id = config.TESTING_ORGANIZATION_ID auth.owner = config.TESTING_ORGANIZATION return auth def github_aclient(owner_name=None, owner_id=None, auth=None): return github.AsyncGithubInstallationClient( get_auth(owner_name, owner_id, auth)) mock.patch.object(github, "aget_client", github_aclient).start() mock.patch.object(branch_updater.gitter, "Gitter", self.get_gitter).start() mock.patch.object(duplicate_pull.gitter, "Gitter", self.get_gitter).start() if not RECORD: # NOTE(sileht): Don't wait exponentialy during replay mock.patch.object(context.Context._ensure_complete.retry, "wait", None).start() # Web authentification always pass mock.patch("hmac.compare_digest", return_value=True).start() branch_prefix_path = os.path.join(self.cassette_library_dir, "branch_prefix") if RECORD: self.BRANCH_PREFIX = datetime.datetime.utcnow().strftime( "%Y%m%d%H%M%S") with open(branch_prefix_path, "w") as f: f.write(self.BRANCH_PREFIX) else: with open(branch_prefix_path, "r") as f: self.BRANCH_PREFIX = f.read() self.master_branch_name = self.get_full_branch_name("master") self.git = self.get_gitter(LOG) await self.git.init() self.addAsyncCleanup(self.git.cleanup) await root.startup() self.app = httpx.AsyncClient(app=root.app, base_url="http://localhost") await self.clear_redis_cache() self.redis_cache = utils.create_aredis_for_cache(max_idle_time=0) self.subscription = subscription.Subscription( self.redis_cache, config.TESTING_ORGANIZATION_ID, self.SUBSCRIPTION_ACTIVE, "You're not nice", frozenset( getattr(subscription.Features, f) for f in subscription.Features.__members__) if self.SUBSCRIPTION_ACTIVE else frozenset(), ) await self.subscription._save_subscription_to_cache() self.user_tokens = user_tokens.UserTokens( self.redis_cache, config.TESTING_ORGANIZATION_ID, { "mergify-test1": config.ORG_ADMIN_GITHUB_APP_OAUTH_TOKEN, "mergify-test3": config.ORG_USER_PERSONAL_TOKEN, }, ) await self.user_tokens.save_to_cache() # Let's start recording cassette = self.recorder.use_cassette("http.json") cassette.__enter__() self.addCleanup(cassette.__exit__) self.client_integration = github.aget_client( config.TESTING_ORGANIZATION, config.TESTING_ORGANIZATION_ID) self.client_admin = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=config.ORG_ADMIN_PERSONAL_TOKEN)) self.client_fork = github.AsyncGithubInstallationClient( auth=github.GithubTokenAuth(token=self.FORK_PERSONAL_TOKEN)) self.addAsyncCleanup(self.client_integration.aclose) self.addAsyncCleanup(self.client_admin.aclose) self.addAsyncCleanup(self.client_fork.aclose) await self.client_admin.item("/user") await self.client_fork.item("/user") if RECORD: assert self.client_admin.auth.owner == "mergify-test1" assert self.client_fork.auth.owner == "mergify-test2" else: self.client_admin.auth.owner = "mergify-test1" self.client_fork.auth.owner = "mergify-test2" self.url_main = f"/repos/mergifyio-testing/{self.REPO_NAME}" self.url_fork = f"/repos/{self.client_fork.auth.owner}/{self.REPO_NAME}" self.git_main = f"{config.GITHUB_URL}/mergifyio-testing/{self.REPO_NAME}" self.git_fork = ( f"{config.GITHUB_URL}/{self.client_fork.auth.owner}/{self.REPO_NAME}" ) self.installation_ctxt = context.Installation( config.TESTING_ORGANIZATION_ID, config.TESTING_ORGANIZATION, self.subscription, self.client_integration, self.redis_cache, ) self.repository_ctxt = context.Repository(self.installation_ctxt, self.REPO_NAME, self.REPO_ID) real_get_subscription = subscription.Subscription.get_subscription async def fake_retrieve_subscription_from_db(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return self.subscription return subscription.Subscription( redis_cache, owner_id, False, "We're just testing", set(), ) async def fake_subscription(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return await real_get_subscription(redis_cache, owner_id) return subscription.Subscription( redis_cache, owner_id, False, "We're just testing", set(), ) mock.patch( "mergify_engine.subscription.Subscription._retrieve_subscription_from_db", side_effect=fake_retrieve_subscription_from_db, ).start() mock.patch( "mergify_engine.subscription.Subscription.get_subscription", side_effect=fake_subscription, ).start() async def fake_retrieve_user_tokens_from_db(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return self.user_tokens return user_tokens.UserTokens(redis_cache, owner_id, {}) real_get_user_tokens = user_tokens.UserTokens.get async def fake_user_tokens(redis_cache, owner_id): if owner_id == config.TESTING_ORGANIZATION_ID: return await real_get_user_tokens(redis_cache, owner_id) return user_tokens.UserTokens(redis_cache, owner_id, {}) mock.patch( "mergify_engine.user_tokens.UserTokens._retrieve_from_db", side_effect=fake_retrieve_user_tokens_from_db, ).start() mock.patch( "mergify_engine.user_tokens.UserTokens.get", side_effect=fake_user_tokens, ).start() self._event_reader = EventReader(self.app) await self._event_reader.drain() # NOTE(sileht): Prepare a fresh redis await self.clear_redis_stream()
async def test_init(redis_cache): user_tokens.UserTokens(redis_cache, 123, [])