def test_returns_short_code_of_expected_length():
    hasher = UrlHasher(get_null_log())
    url = "https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags"

    result = hasher.get_hashed_url(url)

    assert CODE_LENGTH == len(result)
def test_returns_different_results_for_same_input():
    hasher = UrlHasher(get_null_log())
    url = "https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags"

    result1 = hasher.get_hashed_url(url)
    result2 = hasher.get_hashed_url(url)

    assert result1 != result2
def test_should_read_key_from_redis_and_return_none_if_not_found(mocker):
    mocker.patch(REDIS_CREATE_PATH, return_value=None)
    redis_mock = mocker.patch(REDIS_GET_PATH, return_value=None)
    repository = RedisRepository(get_null_log(), CONFIG)
    key = "some key"

    result = repository.read_value(key)

    assert result is None
    redis_mock.assert_called_once_with(key)
def test_should_store_key_to_redis(mocker):
    mocker.patch(REDIS_CREATE_PATH, return_value=None)
    redis_mock = mocker.patch(REDIS_SET_PATH)
    repository = RedisRepository(get_null_log(), CONFIG)
    key = "some key"
    value = "some value"

    repository.save_value(key, value)

    redis_mock.assert_called_once_with(key, value)
def test_should_create_redis_client_with_correct_parameters(mocker):
    strict_redis_mock = mocker.patch(REDIS_CREATE_PATH, return_value=None)
    mocker.patch(REDIS_GET_PATH)
    repository = RedisRepository(get_null_log(), CONFIG)

    repository.read_value("key")

    strict_redis_mock.assert_called_once_with(host=REDIS_HOST,
                                              port=REDIS_PORT,
                                              db=0)
def test_should_read_key_from_redis(mocker):
    mocker.patch(REDIS_CREATE_PATH, return_value=None)
    value = "some value"
    redis_mock = mocker.patch(REDIS_GET_PATH, return_value=value.encode())
    repository = RedisRepository(get_null_log(), CONFIG)
    key = "some key"

    result = repository.read_value(key)

    assert value == result
    redis_mock.assert_called_once_with(key)
def test_saves_original_and_shortened_url_to_repository(mocker):
    mocker.patch(URL_HASHER_PATH, return_value=HASHED_CODE)
    mocker.patch(REPOSITORY_READ_PATH, return_value=None)
    repository_mock = mocker.patch(REPOSITORY_WRITE_PATH)
    test_log = get_null_log()
    repository = RedisRepository(test_log, TEST_CONFIG)
    shortener = Shortener(test_log, TEST_CONFIG, repository)

    shortener.create_shortened_url(ORIGINAL_URL)

    repository_mock.assert_called_once_with(HASHED_CODE, ORIGINAL_URL)
def test_returns_service_url_extended_with_code(mocker):
    hasher_mock = mocker.patch(URL_HASHER_PATH, return_value=HASHED_CODE)
    mocker.patch(REPOSITORY_WRITE_PATH)
    mocker.patch(REPOSITORY_READ_PATH, return_value=None)
    test_log = get_null_log()
    repository = RedisRepository(test_log, TEST_CONFIG)
    shortener = Shortener(test_log, TEST_CONFIG, repository)

    result = shortener.create_shortened_url(ORIGINAL_URL)

    assert SERVICE_URL + HASHED_CODE == result
    hasher_mock.assert_called_once_with(ORIGINAL_URL)
def test_regenerates_and_stores_hash_code_if_it_already_taken(mocker):
    hasher_mock = mocker.patch(URL_HASHER_PATH)
    hasher_mock.side_effect = ["hash1", "hash2", "hash3"]
    repository_read_mock = mocker.patch(REPOSITORY_READ_PATH)
    repository_read_mock.side_effect = ["url1", "url2", None]
    repository_mock = mocker.patch(REPOSITORY_WRITE_PATH)
    test_log = get_null_log()
    repository = RedisRepository(test_log, TEST_CONFIG)
    shortener = Shortener(test_log, TEST_CONFIG, repository)

    shortener.create_shortened_url(ORIGINAL_URL)

    assert 3 == hasher_mock.call_count
    assert 3 == repository_read_mock.call_count
    repository_mock.assert_called_once_with("hash3", ORIGINAL_URL)
def test_should_throw_breaker_error_and_not_call_redis_after_three_fails_on_read(
        mocker):
    mocker.patch(REDIS_CREATE_PATH, return_value=None)
    redis_mock = mocker.patch(REDIS_GET_PATH)
    redis_mock.side_effect = [
        redis.TimeoutError(),
        redis.TimeoutError(),
        redis.TimeoutError()
    ]
    repository = RedisRepository(get_null_log(), CONFIG)

    for _ in range(2):
        with pytest.raises(redis.TimeoutError):
            repository.read_value("key")
    for _ in range(2):
        with pytest.raises(pybreaker.CircuitBreakerError):
            repository.read_value("key")

    assert 3 == redis_mock.call_count