From a14a32159c79ce9bb72a121e6646f7d5c633c32e Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Tue, 20 Feb 2024 18:04:13 -0800 Subject: [PATCH] Add more tests in for caching, still WIP --- src/registrar/models/domain.py | 2 + src/registrar/tests/common.py | 79 +++++++++++++++++ src/registrar/tests/test_models_domain.py | 100 ++++++++++++++++++++-- 3 files changed, 173 insertions(+), 8 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index dca0693c2..f86990a5e 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -1679,6 +1679,8 @@ class Domain(TimeStampedModel, DomainHelper): try: data_response = self._get_or_create_domain() cache = self._extract_data_from_response(data_response) + # print("!!! cache is") + # print(cache) cleaned = self._clean_cache(cache, data_response) self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts) if fetch_hosts: diff --git a/src/registrar/tests/common.py b/src/registrar/tests/common.py index 336740c02..2419c9687 100644 --- a/src/registrar/tests/common.py +++ b/src/registrar/tests/common.py @@ -704,6 +704,43 @@ class MockEppLib(TestCase): ex_date=datetime.date(2023, 5, 25), ) + mockDataInfoDomainSubdomainAndIPAddress = fakedEppObject( + "fakePw", + cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)), + contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)], + hosts=["fake.meow.gov"], + statuses=[ + common.Status(state="serverTransferProhibited", description="", lang="en"), + common.Status(state="inactive", description="", lang="en"), + ], + ex_date=datetime.date(2023, 5, 25), + addrs=[common.Ip(addr="2.0.0.8")], + ) + + mockDataInfoDomainNotSubdomainNoIP = fakedEppObject( + "fakePw", + cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)), + contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)], + hosts=["fake.meow.com"], + statuses=[ + common.Status(state="serverTransferProhibited", description="", lang="en"), + common.Status(state="inactive", description="", lang="en"), + ], + ex_date=datetime.date(2023, 5, 25), + ) + + mockDataInfoDomainSubdomainNoIP = fakedEppObject( + "fakePw", + cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)), + contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)], + hosts=["fake.subdomainwoip.gov"], + statuses=[ + common.Status(state="serverTransferProhibited", description="", lang="en"), + common.Status(state="inactive", description="", lang="en"), + ], + ex_date=datetime.date(2023, 5, 25), + ) + mockDataExtensionDomain = fakedEppObject( "fakePw", cr_date=make_aware(datetime.datetime(2023, 5, 25, 19, 45, 35)), @@ -841,6 +878,24 @@ class MockEppLib(TestCase): addrs=[common.Ip(addr="1.2.3.4"), common.Ip(addr="2.3.4.5")], ) + mockDataInfoHosts1IP = fakedEppObject( + "lastPw", + cr_date=make_aware(datetime.datetime(2023, 8, 25, 19, 45, 35)), + addrs=[common.Ip(addr="2.0.0.8")], + ) + + mockDataInfoHostsNotSubdomainNoIP = fakedEppObject( + "lastPw", + cr_date=make_aware(datetime.datetime(2023, 8, 26, 19, 45, 35)), + addrs=[], + ) + + mockDataInfoHostsSubdomainNoIP = fakedEppObject( + "lastPw", + cr_date=make_aware(datetime.datetime(2023, 8, 27, 19, 45, 35)), + addrs=[], + ) + mockDataHostChange = fakedEppObject("lastPw", cr_date=make_aware(datetime.datetime(2023, 8, 25, 19, 45, 35))) addDsData1 = { "keyTag": 1234, @@ -1002,6 +1057,8 @@ class MockEppLib(TestCase): return self.mockDeleteDomainCommands(_request, cleaned) case commands.RenewDomain: return self.mockRenewDomainCommand(_request, cleaned) + case commands.InfoHost: + return self.mockInfoHostCommmands(_request, cleaned) case _: return MagicMock(res_data=[self.mockDataInfoHosts]) @@ -1016,6 +1073,25 @@ class MockEppLib(TestCase): code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY, ) + # default - mock send + def mockInfoHostCommmands(self, _request, cleaned): + request_name = getattr(_request, "name", None) + + # Define a dictionary to map request names to data and extension values + request_mappings = { + "fake.meow.gov": (self.mockDataInfoHosts1IP, None), # is subdomain and has ip + "fake.meow.com": (self.mockDataInfoHostsNotSubdomainNoIP, None), # not subdomain w no ip + "fake.subdomainwoip.gov": (self.mockDataInfoHostsSubdomainNoIP, None), # subdomain w no ip + } + + # Retrieve the corresponding values from the dictionary + res_data, extensions = request_mappings.get(request_name, (self.mockDataInfoHosts, None)) # default + + return MagicMock( + res_data=[res_data], + extensions=[extensions] if extensions is not None else [], + ) + def mockUpdateHostCommands(self, _request, cleaned): test_ws_ip = common.Ip(addr="1.1. 1.1") addrs_submitted = getattr(_request, "addrs", []) @@ -1097,6 +1173,9 @@ class MockEppLib(TestCase): "defaulttechnical.gov": (self.InfoDomainWithDefaultTechnicalContact, None), "justnameserver.com": (self.justNameserver, None), "meoward.gov": (self.mockDataInfoDomainSubdomain, None), + "meow.gov": (self.mockDataInfoDomainSubdomainAndIPAddress, None), + "fakemeow.gov": (self.mockDataInfoDomainNotSubdomainNoIP, None), + "subdomainwoip.gov": (self.mockDataInfoDomainSubdomainNoIP, None), } # Retrieve the corresponding values from the dictionary diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index f4dea616b..adde4b410 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -1625,7 +1625,65 @@ class TestRegistrantNameservers(MockEppLib): self.assertEqual(nameservers[0][1], ["1.1.1.1"]) patcher.stop() - def test_nameservers_stored_on_fetch_cache(self): + # 1 - is it a subdomain and it has an ip address -- COVERED? + # 2 - is it a subdomain and it doesn't have an ip address + # 3 - no subdomain, it has an ip address -- COVERED + # 4 - no subomdina, doens't have ip address + + def test_nameservers_stored_on_fetch_cache_a_subdomain_with_ip(self): + """ + #1: It is a subdomain, and has an IP address -- referenced by mockDataInfoDomainSubdomainAndIPAddress + fake.meow.com is not a subdomain of fake.gov + """ + with less_console_noise(): + # make the domain + domain, _ = Domain.objects.get_or_create(name="meow.gov", state=Domain.State.READY) + + # mock the get_or_create methods for Host and HostIP + with patch.object(Host.objects, "get_or_create") as mock_host_get_or_create, patch.object( + HostIP.objects, "get_or_create" + ) as mock_host_ip_get_or_create: + mock_host_get_or_create.return_value = (Host(domain=domain), True) + mock_host_ip_get_or_create.return_value = (HostIP(), True) + + # force fetch_cache to be called, which will return above documented mocked hosts + domain.nameservers + + # This is never called? + mock_host_get_or_create.assert_called_once_with(domain=domain, name="fake.meow.gov") + # Retrieve the mocked_host from the return value of the mock + actual_mocked_host, _ = mock_host_get_or_create.return_value + mock_host_ip_get_or_create.assert_called_with(address="2.0.0.8", host=actual_mocked_host) + self.assertEqual(mock_host_ip_get_or_create.call_count, 1) + + def test_nameservers_stored_on_fetch_cache_a_subdomain_without_ip(self): + """ + #2: It is a subdomain, but doesn't has an IP address + """ + with less_console_noise(): + # make the domain + domain, _ = Domain.objects.get_or_create(name="subdomainwoip.gov", state=Domain.State.READY) + + # mock the get_or_create methods for Host and HostIP + # below should do it for mock_host_get_or_create and mock_host_ip_get_or_create right? + with patch.object(Host.objects, "get_or_create") as mock_host_get_or_create, patch.object( + HostIP.objects, "get_or_create" + ) as mock_host_ip_get_or_create: + mock_host_get_or_create.return_value = (Host(domain=domain), True) + mock_host_ip_get_or_create.return_value = (HostIP(), True) + + # force fetch_cache to be called, which will return above documented mocked hosts + domain.nameservers + + # This is never called? + mock_host_get_or_create.assert_called_once_with(domain=domain, name="fake.subdomainwoip.gov") + # Retrieve the mocked_host from the return value of the mock + actual_mocked_host, _ = mock_host_get_or_create.return_value + mock_host_ip_get_or_create.assert_called_with(address="", host=actual_mocked_host) + + self.assertEqual(mock_host_ip_get_or_create.call_count, 1) + + def test_nameservers_stored_on_fetch_cache_not_subdomain_with_ip(self): """ Scenario: Nameservers are stored in db when they are retrieved from fetch_cache. Verify the success of this by asserting get_or_create calls to db. @@ -1633,23 +1691,49 @@ class TestRegistrantNameservers(MockEppLib): of 'fake.host.com' from InfoDomain and an array of 2 IPs: 1.2.3.4 and 2.3.4.5 from InfoHost """ + + """ + #3: Not a subdomain, but it has an IP address returned due to how we return our defaults + fake.host.com is not a subdomain of fake.gov + """ with less_console_noise(): domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) - # mock the get_or_create methods for Host and HostIP + with patch.object(Host.objects, "get_or_create") as mock_host_get_or_create, patch.object( HostIP.objects, "get_or_create" ) as mock_host_ip_get_or_create: - # Set the return value for the mocks - mock_host_get_or_create.return_value = (Host(), True) + mock_host_get_or_create.return_value = (Host(domain=domain), True) mock_host_ip_get_or_create.return_value = (HostIP(), True) + # force fetch_cache to be called, which will return above documented mocked hosts domain.nameservers - # assert that the mocks are called + # # assert that the mocks are called + mock_host_get_or_create.assert_called_once_with(domain=domain, name="fake.host.com") # Retrieve the mocked_host from the return value of the mock - actual_mocked_host, _ = mock_host_get_or_create.return_value - mock_host_ip_get_or_create.assert_called_with(address="2.3.4.5", host=actual_mocked_host) - self.assertEqual(mock_host_ip_get_or_create.call_count, 2) + mock_host_ip_get_or_create.assert_not_called() + self.assertEqual(mock_host_ip_get_or_create.call_count, 0) + + def test_nameservers_stored_on_fetch_cache_not_subdomain_without_ip(self): + """ + #4: Not a subdomain and doesn't has an IP address (not pointing to default) + referenced by self.mockDataInfoDomainNotSubdomainNoIP + """ + with less_console_noise(): + domain, _ = Domain.objects.get_or_create(name="fakemeow.gov", state=Domain.State.READY) + + with patch.object(Host.objects, "get_or_create") as mock_host_get_or_create, patch.object( + HostIP.objects, "get_or_create" + ) as mock_host_ip_get_or_create: + mock_host_get_or_create.return_value = (Host(domain=domain), True) + mock_host_ip_get_or_create.return_value = (HostIP(), True) + + # force fetch_cache to be called, which will return above documented mocked hosts + domain.nameservers + # # assert that the mocks are called + mock_host_get_or_create.assert_called_once_with(domain=domain, name="fake.meow.com") + mock_host_ip_get_or_create.assert_not_called() + self.assertEqual(mock_host_ip_get_or_create.call_count, 0) @skip("not implemented yet") def test_update_is_unsuccessful(self):