import pytest import random import string import re from sherlock.sherlock import sherlock from sherlock.notify import QueryNotify from sherlock.result import QueryStatus #from sherlock_interactives import Interactives def simple_query(sites_info: dict, site: str, username: str) -> QueryStatus: query_notify = QueryNotify() site_data: dict = {} site_data[site] = sites_info[site] return sherlock( username=username, site_data=site_data, query_notify=query_notify, )[site]['status'].status @pytest.mark.online class TestLiveTargets: """Actively test probes against live and trusted targets""" # Known positives should only use sites trusted to be reliable and unchanging @pytest.mark.parametrize('site,username',[ ('GitLab', 'ppfeister'), ('AllMyLinks', 'blue'), ]) def test_known_positives_via_message(self, sites_info, site, username): assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED # Known positives should only use sites trusted to be reliable and unchanging @pytest.mark.parametrize('site,username',[ ('GitHub', 'ppfeister'), ('GitHub', 'sherlock-project'), ('Docker Hub', 'ppfeister'), ('Docker Hub', 'sherlock'), ]) def test_known_positives_via_status_code(self, sites_info, site, username): assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED # Known positives should only use sites trusted to be reliable and unchanging @pytest.mark.parametrize('site,username',[ ('BodyBuilding', 'blue'), ('kofi', 'yeahkenny'), ]) def test_known_positives_via_response_url(self, sites_info, site, username): assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED # Randomly generate usernames of high length and test for positive availability # Randomly generated usernames should be simple alnum for simplicity and high # compatibility. Several attempts may be made ~just in case~ a real username is # generated. @pytest.mark.parametrize('site,random_len',[ ('GitLab', 255), ('Codecademy', 30) ]) def test_likely_negatives_via_message(self, sites_info, site, random_len): num_attempts: int = 3 attempted_usernames: list[str] = [] status: QueryStatus = QueryStatus.CLAIMED for i in range(num_attempts): acceptable_types = string.ascii_letters + string.digits random_handle = ''.join(random.choice(acceptable_types) for _ in range (random_len)) attempted_usernames.append(random_handle) status = simple_query(sites_info=sites_info, site=site, username=random_handle) if status is QueryStatus.AVAILABLE: break assert status is QueryStatus.AVAILABLE, f"Could not validate available username after {num_attempts} attempts with randomly generated usernames {attempted_usernames}." # Randomly generate usernames of high length and test for positive availability # Randomly generated usernames should be simple alnum for simplicity and high # compatibility. Several attempts may be made ~just in case~ a real username is # generated. @pytest.mark.parametrize('site,random_len',[ ('GitHub', 39), ('Docker Hub', 30) ]) def test_likely_negatives_via_status_code(self, sites_info, site, random_len): num_attempts: int = 3 attempted_usernames: list[str] = [] status: QueryStatus = QueryStatus.CLAIMED for i in range(num_attempts): acceptable_types = string.ascii_letters + string.digits random_handle = ''.join(random.choice(acceptable_types) for _ in range (random_len)) attempted_usernames.append(random_handle) status = simple_query(sites_info=sites_info, site=site, username=random_handle) if status is QueryStatus.AVAILABLE: break assert status is QueryStatus.AVAILABLE, f"Could not validate available username after {num_attempts} attempts with randomly generated usernames {attempted_usernames}." def test_username_illegal_regex(sites_info): site: str = 'BitBucket' invalid_handle: str = '*#$Y&*JRE' pattern = re.compile(sites_info[site]['regexCheck']) # Ensure that the username actually fails regex before testing sherlock assert pattern.match(invalid_handle) is None assert simple_query(sites_info=sites_info, site=site, username=invalid_handle) is QueryStatus.ILLEGAL