Resolve race condition when HA auth provider is loading (#21619)

* Resolve race condition when HA auth provider is loading

* Fix

* Add more tests

* Lint
This commit is contained in:
Jason Hu
2019-03-04 15:59:17 -08:00
committed by Paulus Schoutsen
parent d9806f759b
commit d5bdfdb0b3
6 changed files with 110 additions and 16 deletions
+24
View File
@@ -1,4 +1,5 @@
"""Test the HMAC-based One Time Password (MFA) auth module."""
import asyncio
from unittest.mock import patch
from homeassistant import data_entry_flow
@@ -395,3 +396,26 @@ async def test_not_raise_exception_when_service_not_exist(hass):
# wait service call finished
await hass.async_block_till_done()
async def test_race_condition_in_data_loading(hass):
"""Test race condition in the data loading."""
counter = 0
async def mock_load(_):
"""Mock homeassistant.helpers.storage.Store.async_load."""
nonlocal counter
counter += 1
await asyncio.sleep(0)
notify_auth_module = await auth_mfa_module_from_config(hass, {
'type': 'notify'
})
with patch('homeassistant.helpers.storage.Store.async_load',
new=mock_load):
task1 = notify_auth_module.async_validate('user', {'code': 'value'})
task2 = notify_auth_module.async_validate('user', {'code': 'value'})
results = await asyncio.gather(task1, task2, return_exceptions=True)
assert counter == 1
assert results[0] is False
assert results[1] is False
+24
View File
@@ -1,4 +1,5 @@
"""Test the Time-based One Time Password (MFA) auth module."""
import asyncio
from unittest.mock import patch
from homeassistant import data_entry_flow
@@ -128,3 +129,26 @@ async def test_login_flow_validates_mfa(hass):
result['flow_id'], {'code': MOCK_CODE})
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result['data'].id == 'mock-user'
async def test_race_condition_in_data_loading(hass):
"""Test race condition in the data loading."""
counter = 0
async def mock_load(_):
"""Mock of homeassistant.helpers.storage.Store.async_load."""
nonlocal counter
counter += 1
await asyncio.sleep(0)
totp_auth_module = await auth_mfa_module_from_config(hass, {
'type': 'totp'
})
with patch('homeassistant.helpers.storage.Store.async_load',
new=mock_load):
task1 = totp_auth_module.async_validate('user', {'code': 'value'})
task2 = totp_auth_module.async_validate('user', {'code': 'value'})
results = await asyncio.gather(task1, task2, return_exceptions=True)
assert counter == 1
assert results[0] is False
assert results[1] is False
@@ -1,4 +1,5 @@
"""Test the Home Assistant local auth provider."""
import asyncio
from unittest.mock import Mock, patch
import pytest
@@ -288,3 +289,29 @@ async def test_legacy_get_or_create_credentials(hass, legacy_data):
'username': 'hello '
})
assert credentials1 is not credentials3
async def test_race_condition_in_data_loading(hass):
"""Test race condition in the hass_auth.Data loading.
Ref issue: https://github.com/home-assistant/home-assistant/issues/21569
"""
counter = 0
async def mock_load(_):
"""Mock of homeassistant.helpers.storage.Store.async_load."""
nonlocal counter
counter += 1
await asyncio.sleep(0)
provider = hass_auth.HassAuthProvider(hass, auth_store.AuthStore(hass),
{'type': 'homeassistant'})
with patch('homeassistant.helpers.storage.Store.async_load',
new=mock_load):
task1 = provider.async_validate_login('user', 'pass')
task2 = provider.async_validate_login('user', 'pass')
results = await asyncio.gather(task1, task2, return_exceptions=True)
assert counter == 1
assert isinstance(results[0], hass_auth.InvalidAuth)
# results[1] will be a TypeError if race condition occurred
assert isinstance(results[1], hass_auth.InvalidAuth)