"""Tests for data structures.""" import itertools import pytest from availability import datastructures as ds from availability.constants import models STORE_ID_NONEXISTENT = 0 DB_RELEASE_STATUS_INVALID = 'some unknown status string' # Valid values for ReleaseStatus attributes. STORE_RELEASE_IDS = ['ABC123', 456, '', None] STORE_RELEASE_STATUSES = ('any string', '', None) DB_RELEASE_STATUSES_NOT_LIVE = ( models.RELEASE_STATUSES_ENUM.difference( (models.RELEASE_STATUS_LIVE,))) STORE_RELEASE_LIVE_COUNTRIES = (['z', 'US', 'Br'], ['AU']) STORE_RELEASE_LIVE_COUNTRIES_EMPTY = ([], None) def _get_valid_release_kwargs_list(): """ Get all valid combinations of ReleaseStatus kwargs. Construct valid kwargs according to the ReleaseStatus field validation rules. Returns: list: A list of dicts with all valid status combinations. Example: [{ 'store_release_id': 'ABC123', 'db_release_status': 'live', 'store_release_status': 'any string', 'live_countries': ['z', 'US', 'Br'] }, ... ] """ kwargs_list = [] live_statuses_countries_pairs = ( (models.RELEASE_STATUS_LIVE,), STORE_RELEASE_LIVE_COUNTRIES) non_live_statuses_countries_pairs = ( DB_RELEASE_STATUSES_NOT_LIVE, STORE_RELEASE_LIVE_COUNTRIES_EMPTY) # Only valid combinations of live countries and db statuses. for db_statuses, countries in ( live_statuses_countries_pairs, non_live_statuses_countries_pairs): # All combinations of other valid statuses. for (store_release_id, store_release_status, db_release_status, live_countries) in itertools.product( STORE_RELEASE_IDS, STORE_RELEASE_STATUSES, db_statuses, countries): kwargs_list.append(dict( store_release_id=store_release_id, store_release_status=store_release_status, db_release_status=db_release_status, live_countries=live_countries)) return _kwargs_list_extend_with_empty_removed(kwargs_list) def _kwargs_list_extend_with_empty_removed(kwargs_list): """Construct kwargs list to include variants with optional ones removed.""" kwargs_list_copy = kwargs_list[:] for kwargs in kwargs_list_copy: for k, v in kwargs.copy().items(): if not v: del kwargs[k] return kwargs_list + kwargs_list_copy def _release_kwargs_to_expected_attrs(kwargs_dict): """Convert kwargs to expected types of the ReleaseStatus attributes.""" expected_attrs = {} for k in ('store_release_id', 'store_release_status', 'db_release_status'): v = kwargs_dict.get(k) expected_attrs[k] = str(v) if v else None countries = kwargs_dict.get('live_countries', None) expected_attrs['live_countries'] = ( [] if countries is None else sorted(countries)) return expected_attrs @pytest.mark.parametrize('valid_kwargs', _get_valid_release_kwargs_list()) def test_release_status_creation(valid_kwargs): """Test ReleaseStatus object creation with possible kwargs combination.""" status = ds.ReleaseStatus(**valid_kwargs) expected_attrs = _release_kwargs_to_expected_attrs(valid_kwargs) for k, v in expected_attrs.items(): assert getattr(status, k) == v @pytest.mark.parametrize('valid_kwargs', _get_valid_release_kwargs_list()) def test_release_status_attrs_assignment(valid_kwargs): """Test ReleaseStatus valid attribute values assignments.""" status = ds.ReleaseStatus() for k, v in valid_kwargs.items(): setattr(status, k, v) expected_attrs = _release_kwargs_to_expected_attrs(valid_kwargs) for k, v in expected_attrs.items(): assert getattr(status, k) == v def test_release_status_manipulate_unknown_attr(): """Test attempt to set ReleaseStatus unknown attribute.""" status = ds.ReleaseStatus() unknown_attr_name = 'arbitrary_attr' with pytest.raises(AttributeError): setattr(status, unknown_attr_name, 'anything') with pytest.raises(AttributeError): getattr(status, unknown_attr_name) def test_release_status_attr_db_release_status_validation(): """Test ReleaseStatus with invalid db_release_status.""" with pytest.raises(ValueError): ds.ReleaseStatus(db_release_status=DB_RELEASE_STATUS_INVALID) status = ds.ReleaseStatus() with pytest.raises(ValueError): status.db_release_status = DB_RELEASE_STATUS_INVALID def test_release_status_attr_live_countries_empty_conversion(): """Test ReleaseStatus with empty live_countries.""" status = ds.ReleaseStatus() assert status.live_countries == [] status.live_countries = None assert status.live_countries == [] def test_release_status_attr_validation_live_countries_sort(): """Test ReleaseStatus with unsorted live_countries.""" live_countries = ['c', 'b', 'a'] status = ds.ReleaseStatus(live_countries=live_countries) assert status.live_countries == sorted(live_countries) status.live_countries = live_countries assert status.live_countries == sorted(live_countries) def test_release_status_as_dict(): """Test ReleaseStatus conversion to dict.""" status = ds.ReleaseStatus( store_release_id=STORE_RELEASE_IDS[0], store_release_status=STORE_RELEASE_STATUSES[0], live_countries=STORE_RELEASE_LIVE_COUNTRIES[0], db_release_status=models.RELEASE_STATUS_LIVE) d = status.as_dict() assert d == dict( store_release_id=status.store_release_id, store_release_status=status.store_release_status, live_countries=status.live_countries, db_release_status=status.db_release_status) def test_release_status_repr(): """Test ReleaseStatus.__repr__().""" ReleaseStatus = ds.ReleaseStatus # for eval() over repr() to work status = ReleaseStatus( store_release_id=STORE_RELEASE_IDS[0], store_release_status=STORE_RELEASE_STATUSES[0], live_countries=STORE_RELEASE_LIVE_COUNTRIES[0], db_release_status=models.RELEASE_STATUS_LIVE) dict_data = status.as_dict() assert eval(repr(status)).as_dict() == dict_data status.store_release_status = 'foo' assert eval(repr(status)).as_dict() != dict_data def test_release_status_eq(): """Test ReleaseStatus.__eq__().""" status1 = ds.ReleaseStatus( store_release_id=STORE_RELEASE_IDS[0], store_release_status=STORE_RELEASE_STATUSES[0], live_countries=STORE_RELEASE_LIVE_COUNTRIES[0], db_release_status=models.RELEASE_STATUS_LIVE) status2 = ds.ReleaseStatus(**status1.as_dict()) assert status1 == status2 status1.store_release_status = 'foo' assert status1 != status2