Fixed issue #16903 re exception with multiple simultanious writes (#17636)

Reworked tests/components/emulated_hue/test_init.py to not be
dependent on the specific internal implementation of util/jsonn.py
This commit is contained in:
Nicko van Someren 2018-10-23 04:54:03 -04:00 committed by Paulus Schoutsen
parent 44e35b7f52
commit 50f0eac7f3
2 changed files with 69 additions and 67 deletions

View File

@ -4,7 +4,7 @@ from typing import Union, List, Dict
import json
import os
from os import O_WRONLY, O_CREAT, O_TRUNC
import tempfile
from homeassistant.exceptions import HomeAssistantError
@ -46,13 +46,17 @@ def save_json(filename: str, data: Union[List, Dict],
Returns True on success.
"""
tmp_filename = filename + "__TEMP__"
tmp_filename = ""
tmp_path = os.path.split(filename)[0]
try:
json_data = json.dumps(data, sort_keys=True, indent=4)
mode = 0o600 if private else 0o644
with open(os.open(tmp_filename, O_WRONLY | O_CREAT | O_TRUNC, mode),
'w', encoding='utf-8') as fdesc:
# Modern versions of Python tempfile create this file with mode 0o600
with tempfile.NamedTemporaryFile(mode="w", encoding='utf-8',
dir=tmp_path, delete=False) as fdesc:
fdesc.write(json_data)
tmp_filename = fdesc.name
if not private:
os.chmod(tmp_filename, 0o644)
os.replace(tmp_filename, filename)
except TypeError as error:
_LOGGER.exception('Failed to serialize to JSON: %s',

View File

@ -1,7 +1,5 @@
"""Test the Emulated Hue component."""
import json
from unittest.mock import patch, Mock, mock_open, MagicMock
from unittest.mock import patch, Mock, MagicMock
from homeassistant.components.emulated_hue import Config
@ -14,30 +12,30 @@ def test_config_google_home_entity_id_to_number():
'type': 'google_home'
})
mop = mock_open(read_data=json.dumps({'1': 'light.test2'}))
handle = mop()
with patch('homeassistant.components.emulated_hue.load_json',
return_value={'1': 'light.test2'}) as json_loader:
with patch('homeassistant.components.emulated_hue'
'.save_json') as json_saver:
number = conf.entity_id_to_number('light.test')
assert number == '2'
with patch('homeassistant.util.json.open', mop, create=True):
with patch('homeassistant.util.json.os.open', return_value=0):
with patch('homeassistant.util.json.os.replace'):
number = conf.entity_id_to_number('light.test')
assert number == '2'
assert handle.write.call_count == 1
assert json.loads(handle.write.mock_calls[0][1][0]) == {
'1': 'light.test2',
'2': 'light.test',
}
assert json_saver.mock_calls[0][1][1] == {
'1': 'light.test2', '2': 'light.test'
}
number = conf.entity_id_to_number('light.test')
assert number == '2'
assert handle.write.call_count == 1
assert json_saver.call_count == 1
assert json_loader.call_count == 1
number = conf.entity_id_to_number('light.test2')
assert number == '1'
assert handle.write.call_count == 1
number = conf.entity_id_to_number('light.test')
assert number == '2'
assert json_saver.call_count == 1
entity_id = conf.number_to_entity_id('1')
assert entity_id == 'light.test2'
number = conf.entity_id_to_number('light.test2')
assert number == '1'
assert json_saver.call_count == 1
entity_id = conf.number_to_entity_id('1')
assert entity_id == 'light.test2'
def test_config_google_home_entity_id_to_number_altered():
@ -48,30 +46,30 @@ def test_config_google_home_entity_id_to_number_altered():
'type': 'google_home'
})
mop = mock_open(read_data=json.dumps({'21': 'light.test2'}))
handle = mop()
with patch('homeassistant.components.emulated_hue.load_json',
return_value={'21': 'light.test2'}) as json_loader:
with patch('homeassistant.components.emulated_hue'
'.save_json') as json_saver:
number = conf.entity_id_to_number('light.test')
assert number == '22'
assert json_saver.call_count == 1
assert json_loader.call_count == 1
with patch('homeassistant.util.json.open', mop, create=True):
with patch('homeassistant.util.json.os.open', return_value=0):
with patch('homeassistant.util.json.os.replace'):
number = conf.entity_id_to_number('light.test')
assert number == '22'
assert handle.write.call_count == 1
assert json.loads(handle.write.mock_calls[0][1][0]) == {
'21': 'light.test2',
'22': 'light.test',
}
assert json_saver.mock_calls[0][1][1] == {
'21': 'light.test2',
'22': 'light.test',
}
number = conf.entity_id_to_number('light.test')
assert number == '22'
assert handle.write.call_count == 1
number = conf.entity_id_to_number('light.test')
assert number == '22'
assert json_saver.call_count == 1
number = conf.entity_id_to_number('light.test2')
assert number == '21'
assert handle.write.call_count == 1
number = conf.entity_id_to_number('light.test2')
assert number == '21'
assert json_saver.call_count == 1
entity_id = conf.number_to_entity_id('21')
assert entity_id == 'light.test2'
entity_id = conf.number_to_entity_id('21')
assert entity_id == 'light.test2'
def test_config_google_home_entity_id_to_number_empty():
@ -82,29 +80,29 @@ def test_config_google_home_entity_id_to_number_empty():
'type': 'google_home'
})
mop = mock_open(read_data='')
handle = mop()
with patch('homeassistant.components.emulated_hue.load_json',
return_value={}) as json_loader:
with patch('homeassistant.components.emulated_hue'
'.save_json') as json_saver:
number = conf.entity_id_to_number('light.test')
assert number == '1'
assert json_saver.call_count == 1
assert json_loader.call_count == 1
with patch('homeassistant.util.json.open', mop, create=True):
with patch('homeassistant.util.json.os.open', return_value=0):
with patch('homeassistant.util.json.os.replace'):
number = conf.entity_id_to_number('light.test')
assert number == '1'
assert handle.write.call_count == 1
assert json.loads(handle.write.mock_calls[0][1][0]) == {
'1': 'light.test',
}
assert json_saver.mock_calls[0][1][1] == {
'1': 'light.test',
}
number = conf.entity_id_to_number('light.test')
assert number == '1'
assert handle.write.call_count == 1
number = conf.entity_id_to_number('light.test')
assert number == '1'
assert json_saver.call_count == 1
number = conf.entity_id_to_number('light.test2')
assert number == '2'
assert handle.write.call_count == 2
number = conf.entity_id_to_number('light.test2')
assert number == '2'
assert json_saver.call_count == 2
entity_id = conf.number_to_entity_id('2')
assert entity_id == 'light.test2'
entity_id = conf.number_to_entity_id('2')
assert entity_id == 'light.test2'
def test_config_alexa_entity_id_to_number():